Skip to content

Commit

Permalink
Continued working on lowering and resolving generic structures
Browse files Browse the repository at this point in the history
  • Loading branch information
IsaacShelton committed Dec 5, 2024
1 parent 61f51a5 commit d032bab
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 40 deletions.
4 changes: 2 additions & 2 deletions src/lower/datatype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ pub fn lower_type(
resolved_ast,
)?))),
resolved::TypeKind::Void => Ok(ir::Type::Void),
resolved::TypeKind::Structure(_, structure_ref) => {
todo!("lower structure");
resolved::TypeKind::Structure(_, structure_ref, parameters) => {
todo!("instantiate structure");
// Ok(ir::Type::Structure(*structure_ref))
}
resolved::TypeKind::AnonymousStruct() => {
Expand Down
6 changes: 4 additions & 2 deletions src/resolve/core_structure_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ pub fn get_core_structure_info<'a, 'b>(
resolved_ast: &'b resolved::Ast<'a>,
resolved_type: &'a resolved::Type,
source: Source,
) -> Result<(&'b HumanName, StructureRef), ResolveError> {
) -> Result<(&'b HumanName, StructureRef, &'b [resolved::Type]), ResolveError> {
match &resolved_ast
.unalias(resolved_type)
.map_err(|e| ResolveErrorKind::from(e).at(source))?
.kind
{
resolved::TypeKind::Structure(name, structure_ref) => Ok((name, *structure_ref)),
resolved::TypeKind::Structure(name, structure_ref, parameters) => {
Ok((name, *structure_ref, parameters.as_slice()))
}
_ => Err(ResolveErrorKind::CannotCreateStructLiteralForNonStructure {
bad_type: resolved_type.to_string(),
}
Expand Down
2 changes: 1 addition & 1 deletion src/resolve/expr/member_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub fn resolve_member_expr(
) -> Result<TypedExpr, ResolveError> {
let resolved_subject = resolve_expr(ctx, subject, None, Initialized::Require)?;

let (_, structure_ref) =
let (_, structure_ref, parameters) =
get_core_structure_info(ctx.resolved_ast, &resolved_subject.resolved_type, source)?;

let structure = ctx
Expand Down
7 changes: 4 additions & 3 deletions src/resolve/expr/struct_literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ pub fn resolve_struct_literal_expr(
source: Source,
) -> Result<TypedExpr, ResolveError> {
let resolved_struct_type = ctx.type_ctx().resolve(ast_type)?;
let (struct_name, structure_ref) =
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).at(source);
resolved::TypeKind::Structure(struct_name.clone(), structure_ref, parameters.to_vec())
.at(source);

let mut next_index = 0;
let mut resolved_fields = IndexMap::new();
Expand Down Expand Up @@ -118,7 +119,7 @@ pub fn resolve_struct_literal_expr(
.insert(field_name.to_string(), (resolved_expr.expr, index))
.is_some()
{
let (struct_name, _) =
let (struct_name, _, _) =
get_core_structure_info(ctx.resolved_ast, &resolved_struct_type, source)?;

return Err(ResolveErrorKind::FieldSpecifiedMoreThanOnce {
Expand Down
2 changes: 1 addition & 1 deletion src/resolve/function_haystack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ impl FunctionHaystack {
.and_then(|first_type| {
if let Ok(first_type) = ctx.resolved_ast.unalias(first_type) {
match &first_type.kind {
TypeKind::Structure(_, structure_ref) => Some(
TypeKind::Structure(_, structure_ref, _) => Some(
ctx.resolved_ast
.structures
.get(*structure_ref)
Expand Down
6 changes: 5 additions & 1 deletion src/resolve/function_head.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,11 @@ fn collect_constraints(map: &mut HashMap<String, HashSet<Constraint>>, ty: &reso
resolved::TypeKind::FixedArray(fixed_array) => collect_constraints(map, &fixed_array.inner),
resolved::TypeKind::FunctionPointer(_) => todo!(),
resolved::TypeKind::Enum(_, _) => (),
resolved::TypeKind::Structure(_, _) => (),
resolved::TypeKind::Structure(_, _, parameters) => {
for parameter in parameters {
collect_constraints(map, parameter);
}
}
resolved::TypeKind::TypeAlias(_, _) => (),
resolved::TypeKind::Polymorph(name, constraints) => {
let set = map.entry(name.to_string()).or_default();
Expand Down
27 changes: 25 additions & 2 deletions src/resolve/polymorph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl PolyRecipe {
}
resolved::TypeKind::FunctionPointer(_) => todo!(),
resolved::TypeKind::Enum(_, _) => ty.clone(),
resolved::TypeKind::Structure(_, _) => ty.clone(),
resolved::TypeKind::Structure(_, _, _) => ty.clone(),
resolved::TypeKind::TypeAlias(_, _) => ty.clone(),
resolved::TypeKind::Polymorph(name, _) => {
let Some(value) = polymorphs.get(name) else {
Expand Down Expand Up @@ -181,14 +181,37 @@ impl PolyCatalog {
| resolved::TypeKind::Floating(_)
| resolved::TypeKind::Void
| resolved::TypeKind::Enum(_, _)
| resolved::TypeKind::Structure(_, _)
| resolved::TypeKind::TypeAlias(_, _) => {
if *pattern_type == *concrete_type {
Ok(())
} else {
Err(None)
}
}
resolved::TypeKind::Structure(_, structure_ref, parameters) => {
match &concrete_type.kind {
resolved::TypeKind::Structure(
_,
concrete_structure_ref,
concrete_parameters,
) => {
if *structure_ref != *concrete_structure_ref
|| parameters.len() != concrete_parameters.len()
{
return Err(None);
}

for (pattern_parameter, concrete_parameter) in
parameters.iter().zip(concrete_parameters.iter())
{
self.match_type(ctx, pattern_parameter, concrete_parameter)?;
}

Ok(())
}
_ => Err(None),
}
}
resolved::TypeKind::Pointer(pattern_inner) => match &concrete_type.kind {
resolved::TypeKind::Pointer(concrete_inner) => {
self.match_type(ctx, pattern_inner, concrete_inner)
Expand Down
38 changes: 19 additions & 19 deletions src/resolve/type_ctx/find.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,23 @@ impl<'a> ResolveTypeCtx<'a> {
.expect("valid settings id")
.0];

if let Some(name) = name.as_plain_str() {
if let Some(types_in_module) = self.types_in_modules.get(&self.module_fs_node_id) {
if let Some(decl) = types_in_module.get(name) {
if let resolved::TypeKind::Structure(_, structure_ref) = decl.kind {
let parameters = &self
.resolved_ast
.structures
.get(structure_ref)
.unwrap()
.parameters;

if parameters.len() > 0 {
todo!("Handle generics for generic type")
}
}
if !arguments.is_empty() {
eprintln!(
"warning: ResolveTypeCtx does not properly handle compile time arguments yet"
);
}

return Ok(Cow::Borrowed(&decl.kind));
}
}
if let Some(decl) = name
.as_plain_str()
.and_then(|name| {
self.types_in_modules
.get(&self.module_fs_node_id)
.and_then(|types_in_module| types_in_module.get(name))
})
// NOTE: This will need to be map instead at some point
.filter(|decl| decl.num_parameters(self.resolved_ast) == arguments.len())
{
return Ok(Cow::Borrowed(&decl.kind));
}

if !name.namespace.is_empty() {
Expand All @@ -58,7 +56,9 @@ impl<'a> ResolveTypeCtx<'a> {
.flat_map(|dep| settings.dependency_to_module.get(dep))
.flat_map(|fs_node_id| self.types_in_modules.get(fs_node_id))
.flat_map(|decls| decls.get(basename.as_ref()))
.filter(|decl| decl.privacy.is_public());
.filter(|decl| decl.privacy.is_public())
// NOTE: This will need to be flat_map instead at some point
.filter(|decl| decl.num_parameters(self.resolved_ast) == arguments.len());

if let Some(found) = matches.next() {
if matches.next().is_some() {
Expand Down
15 changes: 13 additions & 2 deletions src/resolve/type_definition/prepare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
workspace::fs::FsNodeId,
};
use indexmap::IndexMap;
use itertools::Itertools;

pub fn prepare_type_jobs(
ctx: &mut ResolveCtx,
Expand Down Expand Up @@ -97,8 +98,18 @@ fn prepare_structure(
source: structure.source,
});

let struct_type_kind =
resolved::TypeKind::Structure(HumanName(structure.name.to_string()), structure_ref);
// TODO: Improve the source tracking for these
let polymorphs = structure
.parameters
.keys()
.map(|name| resolved::TypeKind::Polymorph(name.into(), vec![]).at(structure.source))
.collect_vec();

let struct_type_kind = resolved::TypeKind::Structure(
HumanName(structure.name.to_string()),
structure_ref,
polymorphs,
);

ctx.types_in_modules
.entry(module_fs_node_id)
Expand Down
40 changes: 35 additions & 5 deletions src/resolved/datatype/kind/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod function_pointer;
use super::Type;
use crate::{
ast::{fmt_c_integer, CInteger, FloatSize, IntegerBits, IntegerSign},
resolved::{human_name::HumanName, EnumRef, StructureRef, TypeAliasRef},
resolved::{human_name::HumanName, Ast, EnumRef, StructureRef, TypeAliasRef},
source_files::Source,
target::Target,
};
Expand Down Expand Up @@ -36,7 +36,7 @@ pub enum TypeKind {
FixedArray(Box<FixedArray>),
FunctionPointer(FunctionPointer),
Enum(HumanName, EnumRef),
Structure(HumanName, StructureRef),
Structure(HumanName, StructureRef, Vec<Type>),
TypeAlias(HumanName, TypeAliasRef),
Polymorph(String, Vec<Constraint>),
}
Expand Down Expand Up @@ -65,7 +65,9 @@ impl TypeKind {
TypeKind::FixedArray(fixed_array) => fixed_array.inner.kind.contains_polymorph(),
TypeKind::FunctionPointer(_) => todo!(),
TypeKind::Enum(_, _) => false,
TypeKind::Structure(_, _) => false,
TypeKind::Structure(_, _, parameters) => parameters
.iter()
.any(|parameter| parameter.kind.contains_polymorph()),
TypeKind::TypeAlias(_, _) => false,
TypeKind::Polymorph(_, _) => true,
}
Expand All @@ -88,7 +90,7 @@ impl TypeKind {
TypeKind::Floating(_)
| TypeKind::FloatLiteral(_)
| TypeKind::Pointer(_)
| TypeKind::Structure(_, _)
| TypeKind::Structure(_, _, _)
| TypeKind::Void
| TypeKind::AnonymousStruct(..)
| TypeKind::AnonymousUnion(..)
Expand All @@ -99,6 +101,18 @@ impl TypeKind {
| TypeKind::Polymorph(_, _) => None,
}
}

pub fn num_target_parameters(&self, resolved_ast: &Ast) -> usize {
match self {
TypeKind::Structure(_, structure_ref, _) => resolved_ast
.structures
.get(*structure_ref)
.unwrap()
.parameters
.len(),
_ => 0,
}
}
}

impl Display for TypeKind {
Expand Down Expand Up @@ -140,7 +154,23 @@ impl Display for TypeKind {
write!(f, "ptr<{}>", **inner)?;
}
TypeKind::Void => f.write_str("void")?,
TypeKind::Structure(name, _) => write!(f, "{}", name)?,
TypeKind::Structure(name, _, parameters) => {
write!(f, "{}", name)?;

if !parameters.is_empty() {
write!(f, "<")?;

for (i, parameter) in parameters.iter().enumerate() {
write!(f, "{}", parameter)?;

if i + 1 < parameters.len() {
write!(f, ", ")?;
}
}

write!(f, ">")?
}
}
TypeKind::AnonymousStruct() => f.write_str("anonymous-struct")?,
TypeKind::AnonymousUnion() => f.write_str("anonymous-union")?,
TypeKind::AnonymousEnum(..) => f.write_str("anonymous-enum")?,
Expand Down
6 changes: 5 additions & 1 deletion src/resolved/datatype/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ impl Type {
TypeKind::FixedArray(fixed_array) => fixed_array.inner.strip_constraints(),
TypeKind::FunctionPointer(_) => todo!(),
TypeKind::Enum(_, _) => (),
TypeKind::Structure(_, _) => (),
TypeKind::Structure(_, _, parameters) => {
for parameter in parameters {
parameter.strip_constraints();
}
}
TypeKind::TypeAlias(_, _) => (),
TypeKind::Polymorph(_, constraints) => {
constraints.drain(..);
Expand Down
8 changes: 7 additions & 1 deletion src/resolved/type_decl.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{Constraint, TypeKind};
use super::{Ast, Constraint, TypeKind};
use crate::{ast::Privacy, source_files::Source};
use std::collections::HashMap;

Expand All @@ -9,6 +9,12 @@ pub struct TypeDecl {
pub privacy: Privacy,
}

impl TypeDecl {
pub fn num_parameters(&self, resolved_ast: &Ast) -> usize {
self.kind.num_target_parameters(resolved_ast)
}
}

#[derive(Clone, Debug, Default)]
pub struct TypeParameters {
pub parameters: HashMap<String, TypeParameter>,
Expand Down

0 comments on commit d032bab

Please sign in to comment.