mirror of
https://github.com/roc-lang/roc.git
synced 2025-12-23 08:48:03 +00:00
More biuÿbuiltin overrides fixes
This commit is contained in:
parent
d92f479130
commit
ad999acbcd
2 changed files with 103 additions and 31 deletions
|
|
@ -105,38 +105,82 @@ fn replaceStrIsEmptyWithLowLevel(env: *ModuleEnv) !void {
|
|||
|
||||
// Add all low-level operations to the map using full qualified names
|
||||
// Associated items are stored as s_decl with qualified names like "Builtin.Str.is_empty"
|
||||
if (env.common.findIdent("Builtin.Str.is_empty")) |str_is_empty_ident| {
|
||||
try low_level_map.put(str_is_empty_ident, .str_is_empty);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Set.is_empty")) |set_is_empty_ident| {
|
||||
try low_level_map.put(set_is_empty_ident, .set_is_empty);
|
||||
}
|
||||
const str_is_empty_ident = env.common.findIdent("Builtin.Str.is_empty") orelse
|
||||
try env.insertIdent(base.Ident.for_text("Builtin.Str.is_empty"));
|
||||
try low_level_map.put(str_is_empty_ident, .str_is_empty);
|
||||
|
||||
// Iterate through all statements and replace matching e_anno_only with e_low_level
|
||||
const set_is_empty_ident = env.common.findIdent("Builtin.Set.is_empty") orelse
|
||||
try env.insertIdent(base.Ident.for_text("Builtin.Set.is_empty"));
|
||||
try low_level_map.put(set_is_empty_ident, .set_is_empty);
|
||||
|
||||
// Iterate through all statements and replace matching s_type_anno with s_decl containing e_low_level
|
||||
const all_stmts = env.store.sliceStatements(env.all_statements);
|
||||
for (all_stmts) |stmt_idx| {
|
||||
const stmt = env.store.getStatement(stmt_idx);
|
||||
if (stmt == .s_decl) {
|
||||
const decl = stmt.s_decl;
|
||||
const pattern = env.store.getPattern(decl.pattern);
|
||||
if (pattern == .assign) {
|
||||
// Check if this declaration's identifier matches a low-level operation
|
||||
if (low_level_map.get(pattern.assign.ident)) |low_level_op| {
|
||||
// Check if its expression is e_anno_only
|
||||
const expr = env.store.getExpr(decl.expr);
|
||||
if (expr == .e_anno_only) {
|
||||
// Replace with e_low_level by updating the node in the store
|
||||
env.store.nodes.set(@enumFromInt(@intFromEnum(decl.expr)), .{
|
||||
.tag = .expr_low_level,
|
||||
.data_1 = @intFromEnum(low_level_op),
|
||||
.data_2 = 0,
|
||||
.data_3 = 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (stmt == .s_type_anno) {
|
||||
const type_anno = stmt.s_type_anno;
|
||||
// Check if this type annotation's identifier matches a low-level operation
|
||||
if (low_level_map.fetchRemove(type_anno.name)) |entry| {
|
||||
const low_level_op = entry.value;
|
||||
|
||||
// Create e_low_level expression node
|
||||
const expr_node_idx = @intFromEnum(stmt_idx); // Reuse the statement index for the expression
|
||||
const expr_idx: CIR.Expr.Idx = @enumFromInt(expr_node_idx + 1000000); // Offset to avoid collision
|
||||
|
||||
_ = env.store.nodes.append(gpa, .{
|
||||
.tag = .expr_low_level,
|
||||
.data_1 = @intFromEnum(low_level_op),
|
||||
.data_2 = 0,
|
||||
.data_3 = 0,
|
||||
}) catch unreachable;
|
||||
|
||||
// Create identifier pattern node
|
||||
const pattern_idx: CIR.Pattern.Idx = @enumFromInt(expr_node_idx + 2000000); // Different offset
|
||||
_ = env.store.nodes.append(gpa, .{
|
||||
.tag = .pattern_identifier,
|
||||
.data_1 = @bitCast(type_anno.name),
|
||||
.data_2 = 0,
|
||||
.data_3 = 0,
|
||||
}) catch unreachable;
|
||||
|
||||
// Replace the s_type_anno statement node with s_decl
|
||||
// We need to store anno in extra_data
|
||||
const extra_start = @as(u32, @intCast(env.store.extra_data.items.items.len));
|
||||
env.store.extra_data.items.appendSlice(gpa, &[_]u32{
|
||||
1, // has_anno = true
|
||||
@intFromEnum(type_anno.anno),
|
||||
}) catch unreachable;
|
||||
|
||||
env.store.nodes.set(@enumFromInt(@intFromEnum(stmt_idx)), .{
|
||||
.tag = .statement_decl,
|
||||
.data_1 = @intFromEnum(pattern_idx),
|
||||
.data_2 = @intFromEnum(expr_idx),
|
||||
.data_3 = extra_start,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify all low-level operations were found in the builtins
|
||||
if (low_level_map.count() > 0) {
|
||||
var missing_buf = try std.ArrayList(u8).initCapacity(gpa, 512);
|
||||
defer missing_buf.deinit(gpa);
|
||||
const writer = missing_buf.writer(gpa);
|
||||
|
||||
try writer.writeAll("\n\nError: The following low-level operations were not found in Builtin.roc:\n");
|
||||
var iter = low_level_map.iterator();
|
||||
while (iter.next()) |entry| {
|
||||
const ident_text = env.getIdentText(entry.key_ptr.*);
|
||||
const op_name = @tagName(entry.value_ptr.*);
|
||||
try writer.print(" - {s} (mapped to .{s})\n", .{ ident_text, op_name });
|
||||
}
|
||||
try writer.writeAll("\nEither:\n");
|
||||
try writer.writeAll(" 1. Remove the obsolete entry from the low_level_map in builtin_compiler/main.zig, OR\n");
|
||||
try writer.writeAll(" 2. Add a standalone type annotation to Builtin.roc for it to match\n\n");
|
||||
|
||||
std.debug.print("{s}", .{missing_buf.items});
|
||||
return error.LowLevelOperationsNotFound;
|
||||
}
|
||||
}
|
||||
|
||||
/// Build-time compiler that compiles builtin .roc sources into serialized ModuleEnvs.
|
||||
|
|
@ -198,15 +242,16 @@ pub fn main() !void {
|
|||
try builtin_env.common.setNodeIndexById(gpa, set_ident, @intCast(@intFromEnum(set_type_idx)));
|
||||
try builtin_env.common.setNodeIndexById(gpa, str_ident, @intCast(@intFromEnum(str_type_idx)));
|
||||
|
||||
// Replace Str.is_empty's e_anno_only with e_low_level
|
||||
// This transforms the standalone annotation into a low-level builtin operation
|
||||
// This must happen BEFORE transformStrNominalToPrimitive
|
||||
try replaceStrIsEmptyWithLowLevel(builtin_env);
|
||||
|
||||
// Transform Str nominal types to .str primitive types
|
||||
// This must happen BEFORE serialization to ensure the .bin file contains
|
||||
// methods associated with the .str primitive, not a nominal type
|
||||
try transformStrNominalToPrimitive(builtin_env);
|
||||
|
||||
// Replace Str.is_empty's e_anno_only with e_low_level
|
||||
// This transforms the standalone annotation into a low-level builtin operation
|
||||
try replaceStrIsEmptyWithLowLevel(builtin_env);
|
||||
|
||||
// Create output directory
|
||||
try std.fs.cwd().makePath("zig-out/builtins");
|
||||
|
||||
|
|
@ -315,6 +360,30 @@ fn compileModule(
|
|||
try can_result.canonicalizeFile();
|
||||
try can_result.validateForChecking();
|
||||
|
||||
// Check for canonicalization errors
|
||||
const can_diagnostics = try module_env.getDiagnostics();
|
||||
defer gpa.free(can_diagnostics);
|
||||
if (can_diagnostics.len > 0) {
|
||||
std.debug.print("Canonicalization errors in {s}:\n", .{module_name});
|
||||
for (can_diagnostics) |diag| {
|
||||
switch (diag) {
|
||||
.undeclared_type => |d| {
|
||||
const type_name = module_env.getIdentText(d.name);
|
||||
std.debug.print(" - Undeclared type: {s}\n", .{type_name});
|
||||
},
|
||||
.nested_value_not_found => |d| {
|
||||
const parent = module_env.getIdentText(d.parent_name);
|
||||
const nested = module_env.getIdentText(d.nested_name);
|
||||
std.debug.print(" - Nested value not found: {s}.{s}\n", .{ parent, nested });
|
||||
},
|
||||
else => {
|
||||
std.debug.print(" - Diagnostic: {any}\n", .{diag});
|
||||
},
|
||||
}
|
||||
}
|
||||
return error.CanonicalizeError;
|
||||
}
|
||||
|
||||
// 6. Type check
|
||||
// Build the list of other modules for type checking
|
||||
var imported_envs = std.ArrayList(*const ModuleEnv).empty;
|
||||
|
|
|
|||
|
|
@ -68,7 +68,10 @@ Builtin := [].{
|
|||
|
||||
Dict := [EmptyDict].{}
|
||||
|
||||
Set := [EmptySet(Dict)].{
|
||||
is_empty : Set(_elem) -> Bool
|
||||
Set(elem) := [].{
|
||||
is_empty : Set(elem) -> Bool
|
||||
|
||||
is_eq : Set(elem), Set(elem) -> Bool
|
||||
is_eq = |_a, _b| Bool.False
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue