From 5825442fdc599d9ccadda2bcfb923f029eeddb08 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Wed, 28 Aug 2024 05:09:11 +0200 Subject: [PATCH] WIP: try to fix constant ordering --- compiler/src/mir/passes.rs | 22 ++++++++++++++++ compiler/src/type_check/expressions.rs | 35 +++++++++++++++++++++++++- types/src/lib.rs | 14 ++++++++--- 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/compiler/src/mir/passes.rs b/compiler/src/mir/passes.rs index d938fac51..9d6565b11 100644 --- a/compiler/src/mir/passes.rs +++ b/compiler/src/mir/passes.rs @@ -710,6 +710,11 @@ impl<'a> DefineConstants<'a> { mir: &mut Mir, modules: &Vec, ) -> bool { + // TODO: the ordering here is totally busted and assumes that + // definitions always come before usage. Depending on how modules are + // imported and what order they're processed in, this isn't necessarily + // the case. + // Literal constants are defined first, as binary constants may depend // on their values. for module in modules { @@ -740,6 +745,8 @@ impl<'a> DefineConstants<'a> { hir::ConstExpression::Float(ref n) => { Constant::Float(n.value) } + hir::ConstExpression::True(_) => Constant::Bool(true), + hir::ConstExpression::False(_) => Constant::Bool(false), _ => continue, }; @@ -750,6 +757,8 @@ impl<'a> DefineConstants<'a> { /// Defines constants who's values are binary expressions. fn define_binary(&mut self, module: &hir::Module) { + // TODO: this straight up always overwrites the previous values, that's + // dumb. for expr in &module.expressions { if let hir::TopLevelExpression::Constant(n) = expr { let id = n.constant_id.unwrap(); @@ -772,6 +781,19 @@ impl<'a> DefineConstants<'a> { hir::ConstExpression::False(_) => Constant::Bool(false), hir::ConstExpression::ConstantRef(ref n) => match n.kind { types::ConstantKind::Constant(id) => { + // TODO: this fails if we end up referring to a constant + // (e.g. in a binary expression) before it's defined. + if self.mir.constants.get(&id).is_none() { + println!( + "constant {} is missing, type = {}", + id.0, + types::format::format_type( + &self.state.db, + id.value_type(&self.state.db) + ) + ); + } + self.mir.constants.get(&id).cloned().unwrap() } _ => unreachable!(), diff --git a/compiler/src/type_check/expressions.rs b/compiler/src/type_check/expressions.rs index 4036a12df..4e72c227b 100644 --- a/compiler/src/type_check/expressions.rs +++ b/compiler/src/type_check/expressions.rs @@ -641,6 +641,26 @@ impl<'a> DefineConstants<'a> { if node.value.is_simple_literal() == simple_only { self.define_constant(node); } + + // TODO: remove + { + let id = node.constant_id.unwrap(); + + if id.name(&self.state.db).starts_with("SO_LINGER") { + println!( + "{:<15} id = {}, simple = {:<5} {:>5}, type = {:>10}, file = {}", + id.name(&self.state.db), + id.0, + simple_only, + node.value.is_simple_literal(), + types::format::format_type( + &self.state.db, + id.value_type(&self.state.db) + ), + self.module.file(&self.state.db).display() + ); + } + } } } @@ -997,7 +1017,7 @@ impl<'a> CheckConstant<'a> { } fn expression(&mut self, node: &mut hir::ConstExpression) -> TypeRef { - match node { + let typ = match node { hir::ConstExpression::Int(ref mut n) => self.int_literal(n), hir::ConstExpression::Float(ref mut n) => self.float_literal(n), hir::ConstExpression::String(ref mut n) => self.string_literal(n), @@ -1006,7 +1026,20 @@ impl<'a> CheckConstant<'a> { hir::ConstExpression::Binary(ref mut n) => self.binary(n), hir::ConstExpression::ConstantRef(ref mut n) => self.constant(n), hir::ConstExpression::Array(ref mut n) => self.array(n), + }; + + // This shouldn't ever happen, but once upon a time it did due to a bug, + // so this check is here to prevent such a bug from happening again. + if let TypeRef::Unknown = typ { + self.state.diagnostics.error( + DiagnosticId::InvalidType, + "the type of this constant is unknown, this is a compiler bug", + self.file(), + node.location().clone(), + ); } + + typ } fn int_literal(&mut self, node: &mut hir::IntLiteral) -> TypeRef { diff --git a/types/src/lib.rs b/types/src/lib.rs index 599367ec9..b2b40112b 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -3266,7 +3266,7 @@ pub struct Constant { location: Location, name: String, documentation: String, - value_type: TypeRef, + value_type: TypePlaceholderId, visibility: Visibility, } @@ -3284,13 +3284,17 @@ impl Constant { assert!(local_id <= u16::MAX as usize); + let placeholder = TypePlaceholder::alloc(db, None); + + placeholder.assign(db, value_type); + let constant = Constant { id: local_id as u16, module, location, name: name.clone(), documentation: String::new(), - value_type, + value_type: placeholder, visibility, }; @@ -3324,11 +3328,13 @@ impl ConstantId { } pub fn set_value_type(self, db: &mut Database, value_type: TypeRef) { - self.get_mut(db).value_type = value_type; + self.get_mut(db).value_type.assign(db, value_type); } pub fn value_type(self, db: &Database) -> TypeRef { - self.get(db).value_type + let placeholder = self.get(db).value_type; + + placeholder.value(db).unwrap_or(TypeRef::Placeholder(placeholder)) } pub fn is_public(self, db: &Database) -> bool {