Skip to content

Commit

Permalink
WIP: try to fix constant ordering
Browse files Browse the repository at this point in the history
  • Loading branch information
yorickpeterse committed Aug 28, 2024
1 parent 4d038ac commit 5825442
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 5 deletions.
22 changes: 22 additions & 0 deletions compiler/src/mir/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,11 @@ impl<'a> DefineConstants<'a> {
mir: &mut Mir,
modules: &Vec<hir::Module>,
) -> 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 {
Expand Down Expand Up @@ -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,
};

Expand All @@ -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();
Expand All @@ -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!(),
Expand Down
35 changes: 34 additions & 1 deletion compiler/src/type_check/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
);
}
}
}
}

Expand Down Expand Up @@ -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),
Expand All @@ -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 {
Expand Down
14 changes: 10 additions & 4 deletions types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3266,7 +3266,7 @@ pub struct Constant {
location: Location,
name: String,
documentation: String,
value_type: TypeRef,
value_type: TypePlaceholderId,
visibility: Visibility,
}

Expand All @@ -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,
};

Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 5825442

Please sign in to comment.