Skip to content

Commit

Permalink
Finish implementing basic polymorphic structure instantiation along w…
Browse files Browse the repository at this point in the history
…ith polymorphic structure literals
  • Loading branch information
IsaacShelton committed Dec 8, 2024
1 parent 0893c9f commit 4de28c6
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/resolve/expr/member_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
};

pub fn resolve_member_expr(
ctx: &mut ResolveExprCtx<'_, '_>,
ctx: &mut ResolveExprCtx,
subject: &ast::Expr,
field_name: &str,
min_privacy: Privacy,
Expand Down
73 changes: 53 additions & 20 deletions src/resolve/expr/struct_literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,54 @@ use crate::{
conform::{conform_expr, ConformMode, Perform},
core_structure_info::get_core_structure_info,
error::{ResolveError, ResolveErrorKind},
Initialized,
Initialized, PolyCatalog, PolymorphError,
},
resolved::{self, StructLiteral, StructureRef, TypedExpr},
source_files::Source,
};
use indexmap::IndexMap;
use itertools::Itertools;

#[derive(Clone, Debug)]
pub struct FieldInfo {
index: usize,
resolved_type: resolved::Type,
}

fn get_field_info<'a>(
ctx: &'a ResolveExprCtx,
structure_ref: StructureRef,
arguments: &[resolved::Type],
field_name: &str,
) -> (usize, &'a resolved::Field) {
let (index, _, field) = ctx
) -> Result<FieldInfo, PolymorphError> {
let structure = ctx
.resolved_ast
.structures
.get(structure_ref)
.expect("referenced structure to exist")
.expect("referenced structure to exist");

let (index, _, field) = structure
.fields
.get_full::<str>(field_name)
.expect("referenced struct field to exist");
(index, field)

let mut catalog = PolyCatalog::new();

assert!(arguments.len() == structure.parameters.len());

for (name, argument) in structure.parameters.names().zip(arguments.iter()) {
catalog
.put_type(name, argument)
.expect("non-duplicate polymorphic type parameters for structure".into())
}

let recipe = catalog.bake();
let resolved_type = recipe.resolve_type(&field.resolved_type)?;

Ok(FieldInfo {
index,
resolved_type,
})
}

pub fn resolve_struct_literal_expr(
Expand All @@ -41,9 +67,8 @@ pub fn resolve_struct_literal_expr(
let (struct_name, structure_ref, parameters) =
get_core_structure_info(ctx.resolved_ast, &resolved_struct_type, source)?;

let structure_type =
resolved::TypeKind::Structure(struct_name.clone(), structure_ref, parameters.to_vec())
.at(source);
let struct_name = struct_name.clone();
let parameters = parameters.to_vec();

let mut next_index = 0;
let mut resolved_fields = IndexMap::new();
Expand Down Expand Up @@ -91,7 +116,8 @@ pub fn resolve_struct_literal_expr(
)?;

// Lookup additional details required for resolution
let (index, field) = get_field_info(ctx, structure_ref, &field_name);
let field_info = get_field_info(ctx, structure_ref, &parameters, &field_name)
.map_err(ResolveError::from)?;

let mode = match conform_behavior {
ConformBehavior::Adept(_) => ConformMode::Normal,
Expand All @@ -101,7 +127,7 @@ pub fn resolve_struct_literal_expr(
let resolved_expr = conform_expr::<Perform>(
ctx,
&resolved_expr,
&field.resolved_type,
&field_info.resolved_type,
mode,
conform_behavior,
source,
Expand All @@ -110,26 +136,26 @@ pub fn resolve_struct_literal_expr(
ResolveErrorKind::ExpectedTypeForField {
structure: ast_type.to_string(),
field_name: field_name.to_string(),
expected: field.resolved_type.to_string(),
expected: field_info.resolved_type.to_string(),
}
.at(ast_type.source)
})?;

if resolved_fields
.insert(field_name.to_string(), (resolved_expr.expr, index))
.insert(
field_name.to_string(),
(resolved_expr.expr, field_info.index),
)
.is_some()
{
let (struct_name, _, _) =
get_core_structure_info(ctx.resolved_ast, &resolved_struct_type, source)?;

return Err(ResolveErrorKind::FieldSpecifiedMoreThanOnce {
struct_name: struct_name.to_string(),
field_name: field_name.to_string(),
}
.at(ast_type.source));
}

next_index = index + 1;
next_index = field_info.index + 1;
}

let structure = ctx
Expand All @@ -155,10 +181,14 @@ pub fn resolve_struct_literal_expr(
}
FillBehavior::Zeroed => {
for field_name in missing.iter() {
let (index, field) = get_field_info(ctx, structure_ref, field_name);
let zeroed = resolved::ExprKind::Zeroed(Box::new(field.resolved_type.clone()))
.at(source);
resolved_fields.insert(field_name.to_string(), (zeroed, index));
let field_info = get_field_info(ctx, structure_ref, &parameters, field_name)
.map_err(ResolveError::from)?;

let zeroed =
resolved::ExprKind::Zeroed(Box::new(field_info.resolved_type.clone()))
.at(source);

resolved_fields.insert(field_name.to_string(), (zeroed, field_info.index));
}
}
}
Expand All @@ -171,6 +201,9 @@ pub fn resolve_struct_literal_expr(
.map(|(x, (y, z))| (x, y, z))
.collect_vec();

let structure_type =
resolved::TypeKind::Structure(struct_name, structure_ref, parameters).at(source);

Ok(TypedExpr::new(
resolved_struct_type.clone(),
resolved::Expr::new(
Expand Down

0 comments on commit 4de28c6

Please sign in to comment.