Skip to content

Commit

Permalink
Finished implementing simple constraint enforcement for structure typ…
Browse files Browse the repository at this point in the history
…e parameters
  • Loading branch information
IsaacShelton committed Dec 14, 2024
1 parent 8913bdb commit b465338
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/resolve/expr/basic_binary_operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub fn resolve_basic_binary_operator(
ast::BasicBinaryOperator::Add => NumericMode::try_new(resolved_type)
.map(resolved::BasicBinaryOperator::Add)
.or_else(|| {
ctx.constraints
ctx.current_constraints
.satisfies(resolved_type, &Constraint::PrimitiveAdd)
.then(|| resolved::BasicBinaryOperator::PrimitiveAdd(resolved_type.clone()))
}),
Expand Down
2 changes: 1 addition & 1 deletion src/resolve/expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub struct ResolveExprCtx<'a, 'b> {
pub helper_exprs_in_modules: &'b HashMap<FsNodeId, HashMap<String, resolved::HelperExprDecl>>,
pub module_fs_node_id: FsNodeId,
pub physical_fs_node_id: FsNodeId,
pub constraints: CurrentConstraints,
pub current_constraints: CurrentConstraints,
}

impl<'a, 'b> ResolveExprCtx<'a, 'b> {
Expand Down
5 changes: 4 additions & 1 deletion src/resolve/function_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub fn resolve_function_bodies(
helper_exprs_in_modules: &mut ctx.helper_exprs_in_modules,
module_fs_node_id: module_file_id,
physical_fs_node_id: physical_file_id,
constraints,
current_constraints: constraints,
},
&ast_function.stmts,
)?;
Expand Down Expand Up @@ -98,11 +98,14 @@ fn resolve_parameter_variables(
let mut variable_haystack = VariableHaystack::new();

for parameter in ast_function.parameters.required.iter() {
let function = resolved_ast.functions.get(resolved_function_ref).unwrap();

let type_ctx = ResolveTypeCtx::new(
&resolved_ast,
module_file_id,
physical_file_id,
&ctx.types_in_modules,
&function.constraints,
);

let mut resolved_type = type_ctx.resolve(&parameter.ast_type)?;
Expand Down
8 changes: 7 additions & 1 deletion src/resolve/function_head.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,17 @@ pub fn create_function_heads(

for (function_i, function) in file.functions.iter().enumerate() {
let name = ResolvedName::new(module_file_id, &function.name);

let fake_constraints = CurrentConstraints {
constraints: Default::default(),
};

let type_ctx = ResolveTypeCtx::new(
&resolved_ast,
module_file_id,
*physical_file_id,
&ctx.types_in_modules,
&fake_constraints,
);

let is_generic = function.return_type.contains_polymorph().is_some()
Expand Down Expand Up @@ -125,7 +131,7 @@ pub fn create_function_heads(
Ok(())
}

fn collect_constraints(map: &mut HashMap<String, HashSet<Constraint>>, ty: &resolved::Type) {
pub fn collect_constraints(map: &mut HashMap<String, HashSet<Constraint>>, ty: &resolved::Type) {
match &ty.kind {
resolved::TypeKind::Unresolved => panic!(),
resolved::TypeKind::Boolean
Expand Down
5 changes: 4 additions & 1 deletion src/resolve/global_variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ use super::{ctx::ResolveCtx, error::ResolveError, type_ctx::ResolveTypeCtx};
use crate::{
ast::AstWorkspace,
name::{Name, ResolvedName},
resolved::{self, GlobalVarDecl},
resolved::{self, CurrentConstraints, GlobalVarDecl},
};

pub fn resolve_global_variables(
ctx: &mut ResolveCtx,
resolved_ast: &mut resolved::Ast,
ast_workspace: &AstWorkspace,
) -> Result<(), ResolveError> {
let constraints = CurrentConstraints::default();

for (physical_file_id, file) in ast_workspace.files.iter() {
let module_file_id = ast_workspace
.get_owning_module(*physical_file_id)
Expand All @@ -21,6 +23,7 @@ pub fn resolve_global_variables(
module_file_id,
*physical_file_id,
&ctx.types_in_modules,
&constraints,
);

let resolved_type = type_ctx.resolve(&global.ast_type)?;
Expand Down
2 changes: 1 addition & 1 deletion src/resolve/helper_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub fn resolve_helper_expressions(
helper_exprs_in_modules: &ctx.helper_exprs_in_modules,
module_fs_node_id: module_file_id,
physical_fs_node_id: *physical_file_id,
constraints: CurrentConstraints {
current_constraints: CurrentConstraints {
constraints: Default::default(),
},
};
Expand Down
2 changes: 1 addition & 1 deletion src/resolve/polymorph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ impl PolyCatalog {
self.put_type(name, concrete_type).map_err(Some)?;

for constraint in constraints {
if !ctx.constraints.satisfies(concrete_type, constraint) {
if !ctx.current_constraints.satisfies(concrete_type, constraint) {
return Err(None);
}
}
Expand Down
6 changes: 0 additions & 6 deletions src/resolve/type_ctx/find.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,6 @@ impl<'a> ResolveTypeCtx<'a> {
.expect("valid settings id")
.0];

if !arguments.is_empty() {
eprintln!(
"warning: ResolveTypeCtx does not properly handle constraints for compile time arguments yet"
);
}

if let Some(decl) = name
.as_plain_str()
.and_then(|name| {
Expand Down
6 changes: 5 additions & 1 deletion src/resolve/type_ctx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use super::{
use crate::{
ast,
name::ResolvedName,
resolved::{self, Constraint},
resolved::{self, Constraint, CurrentConstraints},
workspace::fs::FsNodeId,
};
use std::collections::{HashMap, HashSet};
Expand All @@ -21,6 +21,7 @@ pub struct ResolveTypeCtx<'a> {
file_fs_node_id: FsNodeId,
types_in_modules: &'a HashMap<FsNodeId, HashMap<String, resolved::TypeDecl>>,
used_aliases_stack: HashSet<ResolvedName>,
current_constraints: &'a CurrentConstraints,
}

impl<'a> ResolveTypeCtx<'a> {
Expand All @@ -29,13 +30,15 @@ impl<'a> ResolveTypeCtx<'a> {
module_fs_node_id: FsNodeId,
file_fs_node_id: FsNodeId,
types_in_modules: &'a HashMap<FsNodeId, HashMap<String, resolved::TypeDecl>>,
current_constraints: &'a CurrentConstraints,
) -> Self {
Self {
resolved_ast,
module_fs_node_id,
file_fs_node_id,
types_in_modules,
used_aliases_stack: Default::default(),
current_constraints,
}
}
}
Expand All @@ -47,6 +50,7 @@ impl<'a, 'b, 'c> From<&'c ResolveExprCtx<'a, 'b>> for ResolveTypeCtx<'c> {
ctx.module_fs_node_id,
ctx.physical_fs_node_id,
ctx.types_in_modules,
&ctx.current_constraints,
)
}
}
Expand Down
15 changes: 12 additions & 3 deletions src/resolve/type_ctx/resolve_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
ast::{self, IntegerBits},
ir::IntegerSign,
resolve::error::{ResolveError, ResolveErrorKind},
resolved::{self, CurrentConstraints},
resolved::{self},
source_files::Source,
};
use std::borrow::Borrow;
Expand Down Expand Up @@ -45,9 +45,18 @@ impl<'a> ResolveTypeCtx<'a> {
.get(*structure_ref)
.expect("referenced struct to exist");

for (name, parameter) in structure.parameters.parameters.iter() {
assert!(arguments.len() == structure.parameters.len());

for (parameter, argument) in
structure.parameters.parameters.values().zip(arguments)
{
for constraint in &parameter.constraints {
todo!("enforce type constraints for structure type usage")
if !self.current_constraints.satisfies(argument, constraint) {
return Err(ResolveErrorKind::ConstraintsNotSatisfiedForType {
name: name.to_string(),
}
.at(ast_type.source));
}
}
}
}
Expand Down
31 changes: 28 additions & 3 deletions src/resolve/type_definition/resolve.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
use crate::{
ast::{self, AstWorkspace},
resolve::{ctx::ResolveCtx, error::ResolveError, job::TypeJob, type_ctx::ResolveTypeCtx},
resolved::{self, EnumRef, StructureRef, TypeAliasRef},
resolve::{
ctx::ResolveCtx,
error::ResolveError,
job::TypeJob,
type_ctx::{resolve_constraints, ResolveTypeCtx},
},
resolved::{self, CurrentConstraints, EnumRef, StructureRef, TypeAliasRef},
workspace::fs::FsNodeId,
};
use std::borrow::Cow;
use std::{
borrow::Cow,
collections::{HashMap, HashSet},
};

pub fn resolve_type_jobs(
ctx: &mut ResolveCtx,
Expand Down Expand Up @@ -68,11 +76,23 @@ fn resolve_structure(
structure_ref: StructureRef,
) -> Result<(), ResolveError> {
for (field_name, field) in structure.fields.iter() {
let mut constraints = HashMap::new();

for (name, parameter) in structure.parameters.iter() {
constraints.insert(
name.into(),
HashSet::from_iter(resolve_constraints(&parameter.constraints)?.drain(..)),
);
}

let constraints = CurrentConstraints { constraints };

let type_ctx = ResolveTypeCtx::new(
&resolved_ast,
module_file_id,
physical_file_id,
&ctx.types_in_modules,
&constraints,
);

let resolved_type = type_ctx.resolve_or_undeclared(&field.ast_type)?;
Expand Down Expand Up @@ -103,11 +123,13 @@ fn resolve_enum(
definition: &ast::Enum,
enum_ref: EnumRef,
) -> Result<(), ResolveError> {
let constraints = CurrentConstraints::default();
let type_ctx = ResolveTypeCtx::new(
&resolved_ast,
module_file_id,
physical_file_id,
&ctx.types_in_modules,
&constraints,
);

let ast_type = definition
Expand All @@ -129,11 +151,14 @@ fn resolve_type_alias(
definition: &ast::TypeAlias,
type_alias_ref: TypeAliasRef,
) -> Result<(), ResolveError> {
let constraints = CurrentConstraints::default();

let type_ctx = ResolveTypeCtx::new(
&resolved_ast,
module_file_id,
physical_file_id,
&ctx.types_in_modules,
&constraints,
);

let resolved_type = type_ctx.resolve_or_undeclared(&definition.value)?;
Expand Down
13 changes: 8 additions & 5 deletions src/resolved/function.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{name::ResolvedName, resolved::*, source_files::Source, tag::Tag};
use std::{collections::HashSet, fmt::Display};

#[derive(Debug, Clone)]
#[derive(Clone, Debug, Default)]
pub struct CurrentConstraints {
pub constraints: HashMap<String, HashSet<Constraint>>,
}
Expand All @@ -11,10 +11,13 @@ impl CurrentConstraints {
match constraint {
Constraint::PrimitiveAdd => match &ty.kind {
TypeKind::Integer(..) | TypeKind::CInteger(..) | TypeKind::Floating(..) => true,
TypeKind::Polymorph(name, _) => self
.constraints
.get(name)
.map_or(false, |set| set.contains(constraint)),
TypeKind::Polymorph(name, constraints) => {
constraints.contains(constraint)
|| self
.constraints
.get(name)
.map_or(false, |in_scope| in_scope.contains(constraint))
}
_ => false,
},
}
Expand Down

0 comments on commit b465338

Please sign in to comment.