Add some comments

This commit is contained in:
Jared Ramirez 2025-12-20 16:34:25 -05:00
parent 4af41808b7
commit aa9e7bd71d
No known key found for this signature in database
GPG key ID: 41158983F521D68C
3 changed files with 34 additions and 16 deletions

View file

@ -650,7 +650,9 @@ const Unifier = struct {
// then we redirect both a & b to the new alias.
const fresh_alias_var = self.fresh(vars, .{ .alias = a_alias }) catch return Error.AllocatorError;
// TODO: Is it possible to loose rank information here? I suspect so...
// These redirects are safe because fresh_alias_var is created at min(a_rank, b_rank).
// Because of this, we do not loose any rank information.
// This is essentially a custom `self.merge` strategy
self.types_store.dangerousSetVarRedirect(vars.a.var_, fresh_alias_var) catch return Error.AllocatorError;
self.types_store.dangerousSetVarRedirect(vars.b.var_, fresh_alias_var) catch return Error.AllocatorError;
},
@ -739,7 +741,9 @@ const Unifier = struct {
// then we redirect both a & b to the new alias.
const fresh_alias_var = self.fresh(vars, .{ .alias = b_alias }) catch return Error.AllocatorError;
// TODO: Is it possible to loose rank information here? I suspect so...
// These redirects are safe because fresh_alias_var is created at min(a_rank, b_rank).
// Because of this, we do not loose any rank information.
// This is essentially a custom `self.merge` strategy
self.types_store.dangerousSetVarRedirect(vars.a.var_, fresh_alias_var) catch return Error.AllocatorError;
self.types_store.dangerousSetVarRedirect(vars.b.var_, fresh_alias_var) catch return Error.AllocatorError;
},

View file

@ -328,9 +328,15 @@ pub const Generalizer = struct {
return group_rank;
},
.alias => |alias| {
// THEORY: Here, we don't need to recurse into the alias backing
// variable, because those variables are have been instantiated
// at the alias's rank.
// THEORY: Here, we don't need to recurse into the backing type because:
// 1. We visit the type arguments (args)
// 2. Anything in the RHS of the alias is either:
// - A reference to an arg (already visited via args)
// - A concrete type (doesn't need rank adjustment)
// So traversing the backing var would be redundant.
//
// We use top_level as a default, as the type container itself
// does not contribute to the rank calculation.
var next_rank = Rank.top_level;
var args_iter = self.store.iterAliasArgs(alias);
while (args_iter.next()) |arg_var| {
@ -341,7 +347,7 @@ pub const Generalizer = struct {
.structure => |flat_type| {
switch (flat_type) {
.empty_record, .empty_tag_union => {
// Empty records/tag unions never need to be generalized
// THEORY: Empty records/tag unions never need to be generalized
return .top_level;
},
.tuple => |tuple| {
@ -353,17 +359,21 @@ pub const Generalizer = struct {
}
return next_rank;
} else {
// Empty tuples never need to be generalized
// THEORY: Empty tuples never need to be generalized
return .top_level;
}
},
.nominal_type => |nominal| {
// TODO: Do we need to recurse into the nominal types backing
// var here? We do not for alias. But here, it may make sense
// to do so, because types can be unified directly against
// a nominal type's backing var.
var next_rank = try self.adjustRank(self.store.getNominalBackingVar(nominal), group_rank, vars_to_generalize);
// THEORY: Here, we don't need to recurse into the backing type because:
// 1. We visit the type arguments (args)
// 2. Anything in the RHS of the nominal type is either:
// - A reference to an arg (already visited via args)
// - A concrete type (doesn't need rank adjustment)
// So traversing the backing var would be redundant.
//
// We use top_level as a default, as the type container itself
// does not contribute to the rank calculation.
var next_rank = Rank.top_level;
var args_iter = self.store.iterNominalArgs(nominal);
while (args_iter.next()) |arg_var| {
next_rank = next_rank.max(try self.adjustRank(arg_var, group_rank, vars_to_generalize));

View file

@ -5,7 +5,11 @@ app [main!] {
main! : List(Str) => Try({}, [Exit(I32)])
main! = |_args| {
utf8 = [120, 121, 122]
_parsed = parse!(utf8, 0, [])?
_parsed =
match parse!(utf8, 0, []) {
Ok(v) => Ok(v)
Err(_) => Err(1)
}
Ok({})
}
@ -91,12 +95,12 @@ TopLevel : [
TypeDefinition({name: Str, type: Type, position: U64}),
]
parse_type = |file, index| {
parse_type = |_file, index| {
Ok((Name("T"), index))
}
parse_block : List(U8), U64, List(Statement) -> Try((List(Statement), U64), Str)
parse_block = |file, index, acc| {
parse_block = |_file, index, acc| {
Ok((acc, index))
}