Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wip] Begin setting up simple unification #7634

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
225 changes: 116 additions & 109 deletions src/check/check_types/unify.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ const std = @import("std");
const Allocator = std.mem.Allocator;
const base = @import("../../base.zig");

const Type = @import("../../types/type.zig").Type;
const roc_type = @import("../../types/type.zig");
const Type = roc_type.Type;
const Mark = roc_type.Mark;
const Rank = roc_type.Rank;
const Descriptor = roc_type.Descriptor;
const Ident = base.Ident;
const ModuleEnv = base.ModuleEnv;

Expand All @@ -19,8 +23,8 @@ pub fn unify(
first: Type.Idx,
second: Type.Idx,
) !UnificationResult {
const first_type = env.type_store.get(first);
const second_type = env.type_store.get(second);
const first_desc = env.type_store.get(first);
const second_desc = env.type_store.get(second);

var result = UnificationResult{
.mismatches = std.ArrayList(TypeMismatch).init(allocator),
Expand All @@ -31,122 +35,125 @@ pub fn unify(
return result;
}

try unifyType(allocator, env, &result, first, first_type, second, second_type);
var ctx = Context{
.allocator = allocator,
.env = env,
.first = first,
.first_desc = first_desc,
.second = second,
.second_desc = second_desc,
.result = &result,
};

try ctx.unify();

return result;
}

fn unifyType(
const Context = struct {
allocator: Allocator,
env: *ModuleEnv,
result: *UnificationResult,
first: Type.Idx,
first_type: Type,
first_desc: *const Descriptor,
second: Type.Idx,
second_type: Type,
) !void {
_ = allocator;
second_desc: *const Descriptor,
result: *UnificationResult,

switch (first_type) {
.bool => {
@panic("todo");
},
.apply => {
@panic("todo");
},
.str => {
@panic("todo");
},
.int => |i| {
switch (i) {
.u8 => @panic("todo"),
.i8 => @panic("todo"),
.u16 => @panic("todo"),
.i16 => @panic("todo"),
.u32 => @panic("todo"),
.i32 => @panic("todo"),
.u64 => @panic("todo"),
.i64 => @panic("todo"),
.u128 => @panic("todo"),
.i128 => @panic("todo"),
}
},
.frac => {
@panic("todo");
},
.flex_var => |opt_name| unifyFlex(env, result, first, opt_name, second, second_type),
.rigid_var => {
@panic("todo");
},
.func => {
@panic("todo");
},
.type_error => {
@panic("todo");
},
fn unify(self: *Context) !void {
switch (self.first_desc.type) {
.bool => {
@panic("todo");
},
.apply => {
@panic("todo");
},
.str => {
@panic("todo");
},
.int => |i| {
switch (i) {
.u8 => @panic("todo"),
.i8 => @panic("todo"),
.u16 => @panic("todo"),
.i16 => @panic("todo"),
.u32 => @panic("todo"),
.i32 => @panic("todo"),
.u64 => @panic("todo"),
.i64 => @panic("todo"),
.u128 => @panic("todo"),
.i128 => @panic("todo"),
}
},
.frac => {
@panic("todo");
},
.flex_var => |opt_name| self.unifyFlex(opt_name),
.rigid_var => {
@panic("todo");
},
.func => {
@panic("todo");
},
.type_error => {
@panic("todo");
},
}
}
}

fn unifyFlex(
env: *ModuleEnv,
result: *UnificationResult,
first: Type.Idx,
opt_name: ?Ident.Idx,
second: Type.Idx,
second_type: Type,
) void {
switch (second_type) {
.flex_var => |other_name| {
// Prefer right's name
const name = other_name orelse opt_name;
merge(env, result, first, second, .{ .flex_var = name });
},
.bool => {
@panic("todo");
},
.apply => {
@panic("todo");
},
.str => {
@panic("todo");
},
.int => |i| {
switch (i) {
.u8 => @panic("todo"),
.i8 => @panic("todo"),
.u16 => @panic("todo"),
.i16 => @panic("todo"),
.u32 => @panic("todo"),
.i32 => @panic("todo"),
.u64 => @panic("todo"),
.i64 => @panic("todo"),
.u128 => @panic("todo"),
.i128 => @panic("todo"),
}
},
.frac => {
@panic("todo");
},
.rigid_var => {
@panic("todo");
},
.func => {
@panic("todo");
},
.type_error => {
@panic("todo");
},
fn unifyFlex(self: *Context, opt_name: ?Ident.Idx) void {
switch (self.second_desc.type) {
.flex_var => |other_name| {
// Prefer right's name
const name = other_name orelse opt_name;
self.merge(.{ .flex_var = name });
},
.bool => {
@panic("todo");
},
.apply => {
@panic("todo");
},
.str => {
@panic("todo");
},
.int => |i| {
switch (i) {
.u8 => @panic("todo"),
.i8 => @panic("todo"),
.u16 => @panic("todo"),
.i16 => @panic("todo"),
.u32 => @panic("todo"),
.i32 => @panic("todo"),
.u64 => @panic("todo"),
.i64 => @panic("todo"),
.u128 => @panic("todo"),
.i128 => @panic("todo"),
}
},
.frac => {
@panic("todo");
},
.rigid_var => {
@panic("todo");
},
.func => {
@panic("todo");
},
.type_error => {
@panic("todo");
},
}
}
}

fn merge(
env: *ModuleEnv,
result: *UnificationResult,
left: Type.Idx,
right: Type.Idx,
type_value: Type,
) void {
env.type_store.set(left, type_value);
env.type_store.set(right, type_value);
result.has_changed = true;
}
fn merge(self: *Context, ty: Type) void {
const rank = self.first_desc.rank.min(self.second_desc.rank);
const desc = Descriptor{
.rank = rank,
.mark = Mark.NONE,
.type = ty,
};

self.env.type_store.merge(self.first, self.second, desc);
self.result.has_changed = true;
}
};
Loading
Loading