Make it compile

This commit is contained in:
Jared Ramirez 2025-09-17 10:50:07 -04:00
parent a32b4c5625
commit fb9dc18a77
No known key found for this signature in database
GPG key ID: 41158983F521D68C
9 changed files with 10 additions and 171 deletions

View file

@ -8,7 +8,6 @@ const std = @import("std");
const base = @import("base");
const parse = @import("parse");
const compile = @import("compile");
const types = @import("types");
const builtins = @import("builtins");
const Can = @import("../Can.zig");
@ -30,58 +29,9 @@ test "fractional literal - basic decimal" {
.e_dec_small => |dec| {
try testing.expectEqual(dec.numerator, 314);
try testing.expectEqual(dec.denominator_power_of_ten, 2);
const expr_as_type_var: types.Var = @enumFromInt(@intFromEnum(canonical_expr.get_idx()));
const resolved = test_env.module_env.types.resolveVar(expr_as_type_var);
switch (resolved.desc.content) {
.structure => |structure| switch (structure) {
.num => |num| switch (num) {
.num_poly => return error.UnexpectedNumPolyType,
.frac_poly => |poly| {
try testing.expect(poly.requirements.fits_in_dec);
},
.frac_unbound => |requirements| {
try testing.expect(requirements.fits_in_dec);
},
else => return error.UnexpectedNumType,
},
else => return error.UnexpectedStructureType,
},
.flex_var => {
// It's an unbound type variable, which is also fine for literals
},
else => {
std.debug.print("Unexpected content type: {}\n", .{resolved.desc.content});
return error.UnexpectedContentType;
},
}
},
.e_frac_dec => |dec| {
_ = dec;
// Also accept e_frac_dec for decimal literals
const expr_as_type_var: types.Var = @enumFromInt(@intFromEnum(canonical_expr.get_idx()));
const resolved = test_env.module_env.types.resolveVar(expr_as_type_var);
switch (resolved.desc.content) {
.structure => |structure| switch (structure) {
.num => |num| switch (num) {
.num_poly => return error.UnexpectedNumPolyType,
.frac_poly => |poly| {
try testing.expect(poly.requirements.fits_in_dec);
},
.frac_unbound => |requirements| {
try testing.expect(requirements.fits_in_dec);
},
else => return error.UnexpectedNumType,
},
else => return error.UnexpectedStructureType,
},
.flex_var => {
// It's an unbound type variable, which is also fine for literals
},
else => {
std.debug.print("Unexpected content type: {}\n", .{resolved.desc.content});
return error.UnexpectedContentType;
},
}
},
else => {
std.debug.print("Unexpected expr type: {}\n", .{expr});
@ -103,88 +53,12 @@ test "fractional literal - scientific notation small" {
// Very small numbers may round to zero when parsed as small decimal
// This is expected behavior when the value is too small for i16 representation
try testing.expectEqual(dec.numerator, 0);
// Still check type requirements
const expr_as_type_var: types.Var = @enumFromInt(@intFromEnum(canonical_expr.get_idx()));
const resolved = test_env.module_env.types.resolveVar(expr_as_type_var);
switch (resolved.desc.content) {
.structure => |structure| switch (structure) {
.num => |num| switch (num) {
.frac_poly => |poly| {
try testing.expect(poly.requirements.fits_in_f32);
try testing.expect(poly.requirements.fits_in_dec);
},
.frac_unbound => |requirements| {
try testing.expect(requirements.fits_in_f32);
try testing.expect(requirements.fits_in_dec);
},
else => return error.UnexpectedNumType,
},
else => return error.UnexpectedStructureType,
},
.flex_var => {
// It's an unbound type variable, which is also fine for literals
},
else => return error.UnexpectedContentType,
}
},
.e_frac_dec => |frac| {
// Scientific notation can also be parsed as RocDec for exact representation
const expr_as_type_var: types.Var = @enumFromInt(@intFromEnum(canonical_expr.get_idx()));
const resolved = test_env.module_env.types.resolveVar(expr_as_type_var);
switch (resolved.desc.content) {
.structure => |structure| switch (structure) {
.num => |num| switch (num) {
.num_poly => return error.UnexpectedNumPolyType,
.frac_poly => |poly| {
// 1.23e-10 is within f32 range, so it should fit (ignoring precision)
try testing.expect(poly.requirements.fits_in_f32);
try testing.expect(poly.requirements.fits_in_dec);
},
.frac_unbound => |requirements| {
// 1.23e-10 is within f32 range, so it should fit (ignoring precision)
try testing.expect(requirements.fits_in_f32);
try testing.expect(requirements.fits_in_dec);
},
else => return error.UnexpectedNumType,
},
else => return error.UnexpectedStructureType,
},
.flex_var => {
// It's an unbound type variable, which is also fine for literals
},
else => return error.UnexpectedContentType,
}
// RocDec stores the value in a special format
_ = frac;
},
.e_frac_f64 => |frac| {
// Or it might be parsed as f64
const expr_as_type_var: types.Var = @enumFromInt(@intFromEnum(canonical_expr.get_idx()));
const resolved = test_env.module_env.types.resolveVar(expr_as_type_var);
switch (resolved.desc.content) {
.structure => |structure| switch (structure) {
.num => |num| switch (num) {
.num_poly => return error.UnexpectedNumPolyType,
.frac_poly => |poly| {
// 1.23e-10 is within f32 range, so it should fit (ignoring precision)
try testing.expect(poly.requirements.fits_in_f32);
try testing.expect(poly.requirements.fits_in_dec);
},
.frac_unbound => |requirements| {
// 1.23e-10 is within f32 range, so it should fit (ignoring precision)
try testing.expect(requirements.fits_in_f32);
try testing.expect(requirements.fits_in_dec);
},
else => return error.UnexpectedNumType,
},
else => return error.UnexpectedStructureType,
},
.flex_var => {
// It's an unbound type variable, which is also fine for literals
},
else => return error.UnexpectedContentType,
}
try testing.expectApproxEqAbs(frac.value, 1.23e-10, 1e-20);
},
else => {
@ -204,27 +78,6 @@ test "fractional literal - scientific notation large (near f64 max)" {
switch (expr) {
.e_frac_f64 => |frac| {
const expr_as_type_var: types.Var = @enumFromInt(@intFromEnum(canonical_expr.get_idx()));
const resolved = test_env.module_env.types.resolveVar(expr_as_type_var);
switch (resolved.desc.content) {
.structure => |structure| switch (structure) {
.num => |num| switch (num) {
.num_poly => return error.UnexpectedNumPolyType,
.frac_poly => |poly| {
try testing.expect(!poly.requirements.fits_in_dec); // Way out of Dec range
},
.frac_unbound => |requirements| {
try testing.expect(!requirements.fits_in_dec); // Way out of Dec range
},
else => return error.UnexpectedNumType,
},
else => return error.UnexpectedStructureType,
},
.flex_var => {
// It's an unbound type variable, which is also fine for literals
},
else => return error.UnexpectedContentType,
}
try testing.expectEqual(frac.value, 1e308);
},
else => {

View file

@ -28,12 +28,6 @@ fn getIntValue(module_env: *ModuleEnv, expr_idx: CIR.Expr.Idx) !i128 {
}
}
fn calculateRequirements(value: i128) types.Num.Int.Requirements {
const bits_needed = types.Num.Int.BitsNeeded.fromValue(@bitCast(value));
return .{ .sign_needed = value < 0, .bits_needed = bits_needed };
}
test "canonicalize simple positive integer" {
const source = "42";
var test_env = try TestEnv.init(source);

View file

@ -1623,7 +1623,7 @@ fn checkExpr(self: *Self, expr_idx: CIR.Expr.Idx, rank: types_mod.Rank, expected
try self.updateVar(expr_var, .{ .structure = .{ .num = .{ .num_compact = .{ .int = suffix } } } }, rank);
} else {
const int_var = try self.freshFromContent(.{ .structure = .{ .num = .{
.int_unbound = Num.IntRequirements.init(),
.int_unbound = num.requirements,
} } }, rank, expr_region);
try self.var_pool.addVarToRank(int_var, rank);

View file

@ -1397,7 +1397,7 @@ pub fn setupSharedMemoryWithModuleEnv(gpa: std.mem.Allocator, roc_file_path: []c
// Type check the module
var checker = try Check.init(shm_allocator, &env.types, &env, &.{}, &env.store.regions, common_idents);
try checker.checkDefs();
try checker.checkFile();
// Copy the ModuleEnv to the allocated space
env_ptr.* = env;

View file

@ -718,7 +718,7 @@ test "ModuleEnv serialization and interpreter evaluation" {
var checker = try Check.init(gpa, &original_env.types, &original_env, &.{}, &original_env.store.regions, common_idents);
defer checker.deinit();
_ = try checker.checkExpr(canonicalized_expr_idx.get_idx());
_ = try checker.checkExprRepl(canonicalized_expr_idx.get_idx());
// Test 1: Evaluate with the original ModuleEnv
{

View file

@ -328,7 +328,7 @@ pub fn parseAndCanonicalizeExpr(allocator: std.mem.Allocator, source: []const u8
checker.* = try Check.init(allocator, &module_env.types, module_env, &.{}, &module_env.store.regions, common_idents);
// Type check the expression
_ = try checker.checkExpr(canonical_expr_idx.get_idx());
_ = try checker.checkExprRepl(canonical_expr_idx.get_idx());
// WORKAROUND: The type checker doesn't set types for binop expressions yet.
// For numeric binops, manually set the type to match the operands.

View file

@ -85,7 +85,7 @@ test "addTypeVar - default layouts for polymorphic types" {
// Flex number var (Num a) defaults to i128
const num_var = try lt.type_store.fresh();
const flex_num_var = try lt.type_store.freshFromContent(.{ .structure = .{ .num = .{ .num_poly = .{ .var_ = num_var, .requirements = .{ .sign_needed = false, .bits_needed = 0 } } } } });
const flex_num_var = try lt.type_store.freshFromContent(.{ .structure = .{ .num = .{ .num_poly = num_var } } });
const num_layout_idx = try lt.layout_store.addTypeVar(flex_num_var, &lt.type_scope);
const num_layout = lt.layout_store.getLayout(num_layout_idx);
try testing.expect(num_layout.tag == .scalar);
@ -93,7 +93,7 @@ test "addTypeVar - default layouts for polymorphic types" {
// Flex int var (Int a) defaults to i128
const int_var = try lt.type_store.fresh();
const flex_int_var = try lt.type_store.freshFromContent(.{ .structure = .{ .num = .{ .int_poly = .{ .var_ = int_var, .requirements = .{ .sign_needed = false, .bits_needed = 0 } } } } });
const flex_int_var = try lt.type_store.freshFromContent(.{ .structure = .{ .num = .{ .int_poly = int_var } } });
const int_layout_idx = try lt.layout_store.addTypeVar(flex_int_var, &lt.type_scope);
const int_layout = lt.layout_store.getLayout(int_layout_idx);
try testing.expect(int_layout.tag == .scalar);
@ -101,7 +101,7 @@ test "addTypeVar - default layouts for polymorphic types" {
// Flex frac var (Frac a) defaults to dec
const frac_var = try lt.type_store.fresh();
const flex_frac_var = try lt.type_store.freshFromContent(.{ .structure = .{ .num = .{ .frac_poly = .{ .var_ = frac_var, .requirements = .{ .fits_in_f32 = false, .fits_in_dec = true } } } } });
const flex_frac_var = try lt.type_store.freshFromContent(.{ .structure = .{ .num = .{ .frac_poly = frac_var } } });
const frac_layout_idx = try lt.layout_store.addTypeVar(flex_frac_var, &lt.type_scope);
const frac_layout = lt.layout_store.getLayout(frac_layout_idx);
try testing.expect(frac_layout.tag == .scalar);

View file

@ -216,7 +216,7 @@ test "Repl - minimal interpreter integration" {
var checker = try Check.init(gpa, &module_env.types, cir, &.{}, &cir.store.regions, common_idents);
defer checker.deinit();
_ = try checker.checkExpr(canonical_expr_idx.get_idx());
_ = try checker.checkExprRepl(canonical_expr_idx.get_idx());
// Step 6: Create interpreter
var interpreter = try Interpreter.init(gpa, &module_env);

View file

@ -1111,11 +1111,7 @@ test "resolveVarAndCompressPath - no-op on already root" {
defer store.deinit();
const num_flex = try store.fresh();
const requirements = Num.IntRequirements{
.sign_needed = false,
.bits_needed = 0,
};
const num = Content{ .structure = .{ .num = .{ .num_poly = .{ .var_ = num_flex, .requirements = requirements } } } };
const num = Content{ .structure = .{ .num = .{ .num_poly = num_flex } } };
const num_var = try store.freshFromContent(num);
const result = store.resolveVarAndCompressPath(num_var);
@ -1132,11 +1128,7 @@ test "resolveVarAndCompressPath - flattens redirect chain to structure" {
defer store.deinit();
const num_flex = try store.fresh();
const requirements = Num.IntRequirements{
.sign_needed = false,
.bits_needed = 0,
};
const num = Content{ .structure = .{ .num = .{ .num_poly = .{ .var_ = num_flex, .requirements = requirements } } } };
const num = Content{ .structure = .{ .num = .{ .num_poly = num_flex } } };
const c = try store.freshFromContent(num);
const b = try store.freshRedirect(c);
const a = try store.freshRedirect(b);