Skip to content

Update html snapshots #7940

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

Merged
merged 1 commit into from
Jul 5, 2025
Merged
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
20 changes: 13 additions & 7 deletions src/base/SExpr.zig
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ const PlainTextSExprWriter = struct {
_ = self;
// No-op for plain text
}

pub fn writeIndent(self: *@This(), tabs: usize) !void {
for (0..tabs) |_| {
try self.writer.writeByte('\t');
}
}
};

/// HTML writer implementation with syntax highlighting
Expand Down Expand Up @@ -108,6 +114,12 @@ const HtmlSExprWriter = struct {
try self.writer.writeAll("</span>");
}

pub fn writeIndent(self: *@This(), tabs: usize) !void {
for (0..tabs) |_| {
try self.writer.writeAll(" ");
}
}

pub fn deinit(self: *@This()) !void {
if (self.color_active) {
try self.writer.writeAll("</span>");
Expand Down Expand Up @@ -351,7 +363,7 @@ fn toStringImpl(node: SExpr, writer_impl: anytype, indent: usize) !void {
try writer_impl.print("\n", .{});

// Print indentation
try writeIndentImpl(writer_impl, indent + 1);
try writer_impl.writeIndent(indent + 1);

try child.toStringImpl(writer_impl, indent + 1);
}
Expand Down Expand Up @@ -386,12 +398,6 @@ pub fn toHtml(node: SExpr, writer: std.io.AnyWriter) void {
};
}

fn writeIndentImpl(writer_impl: anytype, tabs: usize) !void {
for (0..tabs) |_| {
try writer_impl.print("\t", .{});
}
}

fn writeIndent(writer: std.io.AnyWriter, tabs: usize) !void {
for (0..tabs) |_| {
try writer.writeByte('\t');
Expand Down
59 changes: 41 additions & 18 deletions src/check/canonicalize/CIR.zig
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ pub const TypeHeader = struct {
pub fn toSExpr(self: *const @This(), ir: *const CIR) SExpr {
const gpa = ir.env.gpa;
var node = SExpr.init(gpa, "ty-header");
node.appendRegion(gpa, ir.calcRegionInfo(self.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, self.region);

// Add the type name
node.appendStringAttr(gpa, "name", ir.getIdentText(self.name));
Expand Down Expand Up @@ -746,7 +746,7 @@ pub const Annotation = struct {
_ = line_starts;
const gpa = ir.env.gpa;
var node = SExpr.init(gpa, "annotation");
node.appendRegion(gpa, ir.calcRegionInfo(self.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, self.region);

// Add the declared type annotation structure
var type_anno_node = SExpr.init(gpa, "declared-type");
Expand Down Expand Up @@ -791,7 +791,7 @@ pub const ExternalDecl = struct {
const gpa = ir.env.gpa;

var node = SExpr.init(gpa, "ext-decl");
node.appendRegion(gpa, ir.calcRegionInfo(self.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, self.region);

// Add qualified name
const qualified_name_str = ir.getIdentText(self.qualified_name);
Expand Down Expand Up @@ -1016,16 +1016,33 @@ pub fn calcRegionInfo(self: *const CIR, region: Region) base.RegionInfo {
return info;
}

/// Append region information to an S-expression node for a given index in the Canonical IR.
pub fn appendRegionInfoToSexprNode(ir: *const CIR, node: *SExpr, idx: anytype) void {
const region = ir.store.getNodeRegion(@enumFromInt(@intFromEnum(idx)));
ir.appendRegionInfoToSexprNodeFromRegion(node, region);
}

/// Append region information to an S-expression node from a specific region.
pub fn appendRegionInfoToSexprNodeFromRegion(ir: *const CIR, node: *SExpr, region: Region) void {
const info = ir.calcRegionInfo(region);
node.appendByteRange(
ir.env.gpa,
info,
region.start.offset,
region.end.offset,
);
}

Comment on lines +1019 to +1035
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are long names... much descriptive. 😄

/// Get region information for a node in the Canonical IR.
pub fn getNodeRegionInfo(ir: *const CIR, idx: anytype) base.RegionInfo {
const region = ir.store.getNodeRegion(@enumFromInt(@intFromEnum(idx)));
return ir.calcRegionInfo(region);
}

/// Helper function to convert type information from the Canonical IR to a string
/// Helper function to convert type information from the Canonical IR to an SExpr node
/// in S-expression format for snapshot testing. Implements the definition-focused
/// format showing final types for defs, expressions, and builtins.
pub fn toSexprTypesStr(ir: *CIR, writer: std.io.AnyWriter, maybe_expr_idx: ?Expr.Idx, source: []const u8) !void {
pub fn toSexprTypes(ir: *CIR, maybe_expr_idx: ?Expr.Idx, source: []const u8) SExpr {
// Set temporary source for region info calculation during SExpr generation
ir.temp_source_for_sexpr = source;
defer ir.temp_source_for_sexpr = null;
Expand All @@ -1042,12 +1059,11 @@ pub fn toSexprTypesStr(ir: *CIR, writer: std.io.AnyWriter, maybe_expr_idx: ?Expr
const expr_var = @as(types.Var, @enumFromInt(@intFromEnum(expr_idx)));

var expr_node = SExpr.init(gpa, "expr");
defer expr_node.deinit(gpa);

expr_node.appendRegion(gpa, ir.getNodeRegionInfo(expr_idx));
ir.appendRegionInfoToSexprNode(&expr_node, expr_idx);

if (@intFromEnum(expr_var) > ir.env.types.slots.backing.items.len) {
const unknown_node = SExpr.init(gpa, "unknown");
var unknown_node = SExpr.init(gpa, "unknown");
expr_node.appendNode(gpa, &unknown_node);
} else {
if (type_writer.writeVar(expr_var)) {
Expand All @@ -1057,10 +1073,9 @@ pub fn toSexprTypesStr(ir: *CIR, writer: std.io.AnyWriter, maybe_expr_idx: ?Expr
}
}

expr_node.toStringPretty(writer);
return expr_node;
} else {
var root_node = SExpr.init(gpa, "inferred-types");
defer root_node.deinit(gpa);

// Collect definitions
var defs_node = SExpr.init(gpa, "defs");
Expand All @@ -1075,15 +1090,15 @@ pub fn toSexprTypesStr(ir: *CIR, writer: std.io.AnyWriter, maybe_expr_idx: ?Expr
.assign => |assign_pat| {
var def_node = SExpr.init(gpa, "patt");

def_node.appendRegion(gpa, ir.calcRegionInfo(assign_pat.region));
ir.appendRegionInfoToSexprNodeFromRegion(&def_node, assign_pat.region);

// Get the type variable for this definition
// Each definition has a type_var at its node index which represents the type of the definition
const def_var = try ir.idxToTypeVar(&ir.env.types, def_idx);
const def_var = ir.idxToTypeVar(&ir.env.types, def_idx) catch |err| exitOnOom(err);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have been slowly moving back to using try instead of exitOnOom everywhere.

// Clear the buffer and write the type
type_string_buf.clearRetainingCapacity();
try type_writer.writeVar(def_var);
type_writer.writeVar(def_var) catch |err| exitOnOom(err);
def_node.appendStringAttr(gpa, "type", type_string_buf.items);

defs_node.appendNode(gpa, &def_node);
Expand All @@ -1109,16 +1124,15 @@ pub fn toSexprTypesStr(ir: *CIR, writer: std.io.AnyWriter, maybe_expr_idx: ?Expr
const expr_var = @as(types.Var, @enumFromInt(@intFromEnum(def.expr)));

var expr_node = SExpr.init(gpa, "expr");
expr_node.appendRegion(gpa, ir.calcRegionInfo(def.expr_region));
// expr_node.appendUnsignedInt(gpa, @intFromEnum(expr_var));
ir.appendRegionInfoToSexprNodeFromRegion(&expr_node, def.expr_region);

if (@intFromEnum(expr_var) > ir.env.types.slots.backing.items.len) {
const unknown_node = SExpr.init(gpa, "unknown");
var unknown_node = SExpr.init(gpa, "unknown");
expr_node.appendNode(gpa, &unknown_node);
} else {
// Clear the buffer and write the type
type_string_buf.clearRetainingCapacity();
try type_writer.writeVar(expr_var);
type_writer.writeVar(expr_var) catch |err| exitOnOom(err);
expr_node.appendStringAttr(gpa, "type", type_string_buf.items);
}

Expand All @@ -1127,6 +1141,15 @@ pub fn toSexprTypesStr(ir: *CIR, writer: std.io.AnyWriter, maybe_expr_idx: ?Expr

root_node.appendNode(gpa, &expressions_node);

root_node.toStringPretty(writer);
return root_node;
}
}

/// Helper function to convert type information from the Canonical IR to a string
/// in S-expression format for snapshot testing. Calls `toSexprTypes` and writes the result.
pub fn toSexprTypesStr(ir: *CIR, writer: std.io.AnyWriter, maybe_expr_idx: ?Expr.Idx, source: []const u8) !void {
const gpa = ir.env.gpa;
var node = toSexprTypes(ir, maybe_expr_idx, source);
defer node.deinit(gpa);
node.toStringPretty(writer);
}
46 changes: 23 additions & 23 deletions src/check/canonicalize/Expression.zig
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ pub const Expr = union(enum) {
switch (self.*) {
.e_int => |int_expr| {
var node = SExpr.init(gpa, "e-int");
node.appendRegion(gpa, ir.calcRegionInfo(int_expr.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, int_expr.region);

// Add value
const value_i128: i128 = @bitCast(int_expr.value.bytes);
Expand All @@ -428,7 +428,7 @@ pub const Expr = union(enum) {
},
.e_frac_f64 => |e| {
var node = SExpr.init(gpa, "e-frac-f64");
node.appendRegion(gpa, ir.calcRegionInfo(e.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, e.region);

// Add value
var value_buf: [512]u8 = undefined;
Expand All @@ -445,7 +445,7 @@ pub const Expr = union(enum) {
},
.e_frac_dec => |e| {
var node = SExpr.init(gpa, "e-frac-dec");
node.appendRegion(gpa, ir.calcRegionInfo(e.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, e.region);

// Add value (convert RocDec to string)
// RocDec has 18 decimal places, so divide by 10^18
Expand All @@ -464,7 +464,7 @@ pub const Expr = union(enum) {
},
.e_dec_small => |e| {
var node = SExpr.init(gpa, "e-dec-small");
node.appendRegion(gpa, ir.calcRegionInfo(e.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, e.region);

// Add numerator and denominator_power_of_ten
var num_buf: [32]u8 = undefined;
Expand Down Expand Up @@ -495,7 +495,7 @@ pub const Expr = union(enum) {
},
.e_str_segment => |e| {
var str_node = SExpr.init(gpa, "e-literal");
str_node.appendRegion(gpa, ir.calcRegionInfo(e.region));
ir.appendRegionInfoToSexprNodeFromRegion(&str_node, e.region);

const value = ir.env.strings.get(e.literal);
str_node.appendStringAttr(gpa, "string", value);
Expand All @@ -504,7 +504,7 @@ pub const Expr = union(enum) {
},
.e_str => |e| {
var str_node = SExpr.init(gpa, "e-string");
str_node.appendRegion(gpa, ir.calcRegionInfo(e.region));
ir.appendRegionInfoToSexprNodeFromRegion(&str_node, e.region);

for (ir.store.sliceExpr(e.span)) |segment| {
var segment_node = ir.store.getExpr(segment).toSExpr(ir);
Expand All @@ -515,7 +515,7 @@ pub const Expr = union(enum) {
},
.e_list => |l| {
var list_node = SExpr.init(gpa, "e-list");
list_node.appendRegion(gpa, ir.calcRegionInfo(l.region));
ir.appendRegionInfoToSexprNodeFromRegion(&list_node, l.region);

// Add list elements
var elems_node = SExpr.init(gpa, "elems");
Expand All @@ -529,12 +529,12 @@ pub const Expr = union(enum) {
},
.e_empty_list => |e| {
var empty_list_node = SExpr.init(gpa, "e-empty_list");
empty_list_node.appendRegion(gpa, ir.calcRegionInfo(e.region));
ir.appendRegionInfoToSexprNodeFromRegion(&empty_list_node, e.region);
return empty_list_node;
},
.e_tuple => |t| {
var node = SExpr.init(gpa, "e-tuple");
node.appendRegion(gpa, ir.calcRegionInfo(t.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, t.region);

// Add tuple elements
var elems_node = SExpr.init(gpa, "elems");
Expand All @@ -548,10 +548,10 @@ pub const Expr = union(enum) {
},
.e_lookup_local => |local| {
var lookup_node = SExpr.init(gpa, "e-lookup-local");
lookup_node.appendRegion(gpa, ir.calcRegionInfo(local.region));
ir.appendRegionInfoToSexprNodeFromRegion(&lookup_node, local.region);

var pattern_node = SExpr.init(gpa, "pattern");
pattern_node.appendRegion(gpa, ir.getNodeRegionInfo(local.pattern_idx));
ir.appendRegionInfoToSexprNode(&pattern_node, local.pattern_idx);
lookup_node.appendNode(gpa, &pattern_node);

return lookup_node;
Expand All @@ -566,7 +566,7 @@ pub const Expr = union(enum) {
},
.e_match => |e| {
var node = SExpr.init(gpa, "e-match");
node.appendRegion(gpa, ir.calcRegionInfo(e.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, e.region);

var match_sexpr = e.toSExpr(ir);
node.appendNode(gpa, &match_sexpr);
Expand All @@ -575,7 +575,7 @@ pub const Expr = union(enum) {
},
.e_if => |if_expr| {
var node = SExpr.init(gpa, "e-if");
node.appendRegion(gpa, ir.calcRegionInfo(if_expr.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, if_expr.region);

// Add branches
var branches_node = SExpr.init(gpa, "if-branches");
Expand Down Expand Up @@ -610,7 +610,7 @@ pub const Expr = union(enum) {
},
.e_call => |c| {
var call_node = SExpr.init(gpa, "e-call");
call_node.appendRegion(gpa, ir.calcRegionInfo(c.region));
ir.appendRegionInfoToSexprNodeFromRegion(&call_node, c.region);

// Get all expressions from the args span
const all_exprs = ir.store.exprSlice(c.args);
Expand All @@ -635,7 +635,7 @@ pub const Expr = union(enum) {
},
.e_record => |record_expr| {
var record_node = SExpr.init(gpa, "e-record");
record_node.appendRegion(gpa, ir.calcRegionInfo(record_expr.region));
ir.appendRegionInfoToSexprNodeFromRegion(&record_node, record_expr.region);

// Add fields
var fields_node = SExpr.init(gpa, "fields");
Expand All @@ -649,12 +649,12 @@ pub const Expr = union(enum) {
},
.e_empty_record => |e| {
var empty_record_node = SExpr.init(gpa, "e-empty_record");
empty_record_node.appendRegion(gpa, ir.calcRegionInfo(e.region));
ir.appendRegionInfoToSexprNodeFromRegion(&empty_record_node, e.region);
return empty_record_node;
},
.e_block => |block_expr| {
var block_node = SExpr.init(gpa, "e-block");
block_node.appendRegion(gpa, ir.calcRegionInfo(block_expr.region));
ir.appendRegionInfoToSexprNodeFromRegion(&block_node, block_expr.region);

// Add statements
for (ir.store.sliceStatements(block_expr.stmts)) |stmt_idx| {
Expand All @@ -670,7 +670,7 @@ pub const Expr = union(enum) {
},
.e_tag => |tag_expr| {
var node = SExpr.init(gpa, "e-tag");
node.appendRegion(gpa, ir.calcRegionInfo(tag_expr.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, tag_expr.region);

// Add name
node.appendStringAttr(gpa, "name", ir.env.idents.getText(tag_expr.name));
Expand All @@ -682,7 +682,7 @@ pub const Expr = union(enum) {
},
.e_zero_argument_tag => |tag_expr| {
var node = SExpr.init(gpa, "e-zero-argument-tag");
node.appendRegion(gpa, ir.calcRegionInfo(tag_expr.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, tag_expr.region);

// Add closure_name
node.appendStringAttr(gpa, "closure", ir.getIdentText(tag_expr.closure_name));
Expand All @@ -694,7 +694,7 @@ pub const Expr = union(enum) {
},
.e_lambda => |lambda_expr| {
var node = SExpr.init(gpa, "e-lambda");
node.appendRegion(gpa, ir.calcRegionInfo(lambda_expr.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, lambda_expr.region);

// Handle args span
var args_node = SExpr.init(gpa, "args");
Expand All @@ -712,7 +712,7 @@ pub const Expr = union(enum) {
},
.e_binop => |e| {
var node = SExpr.init(gpa, "e-binop");
node.appendRegion(gpa, ir.calcRegionInfo(e.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, e.region);

node.appendStringAttr(gpa, "op", @tagName(e.op));

Expand All @@ -726,7 +726,7 @@ pub const Expr = union(enum) {
},
.e_dot_access => |e| {
var node = SExpr.init(gpa, "e-dot-access");
node.appendRegion(gpa, ir.calcRegionInfo(e.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, e.region);

var receiver_node = SExpr.init(gpa, "receiver");
var expr_node = ir.store.getExpr(e.receiver).toSExpr(ir);
Expand Down Expand Up @@ -883,7 +883,7 @@ pub const Expr = union(enum) {
const gpa = ir.env.gpa;
var node = SExpr.init(gpa, "match");

node.appendRegion(gpa, ir.calcRegionInfo(self.region));
ir.appendRegionInfoToSexprNodeFromRegion(&node, self.region);

var cond_node = SExpr.init(gpa, "cond");
const cond_expr = ir.store.getExpr(self.cond);
Expand Down
Loading
Loading