Skip to content

Commit

Permalink
Rough implementations of IRs for all stages
Browse files Browse the repository at this point in the history
  • Loading branch information
smores56 committed Feb 5, 2025
1 parent 5e4ff44 commit 5a4095a
Show file tree
Hide file tree
Showing 33 changed files with 3,668 additions and 0 deletions.
52 changes: 52 additions & 0 deletions src/base.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const region = @import("base/region.zig");
const symbol = @import("base/symbol.zig");
const module = @import("base/module.zig");
const package = @import("base/package.zig");
const primitive = @import("base/primitive.zig");
const env = @import("base/env.zig");

pub const Region = region.Region;
pub const Position = region.Position;
pub const LineAndColumn = region.LineAndColumn;

pub const Ident = symbol.Ident;
pub const IdentAttributes = symbol.IdentAttributes;
pub const IdentProblems = symbol.IdentProblems;
pub const IdentId = symbol.IdentId;
pub const IdentStore = symbol.IdentStore;
pub const Symbol = symbol.Symbol;
pub const SymbolStore = symbol.SymbolStore;

pub const Module = module.Module;
pub const ModuleId = module.ModuleId;
pub const ModuleStore = module.ModuleStore;

pub const Package = package.Package;
pub const PackageId = package.PackageId;
pub const PackageStore = package.PackageStore;

pub const Primitive = primitive.Primitive;
pub const Literal = primitive.Literal;

pub const ModuleEnv = env.ModuleEnv;
pub const GlobalEnv = env.GlobalEnv;

pub const Recursive = enum {
NotRecursive,
Recursive,
TailRecursive,
};

// TODO: can this be smaller than u32?
/// Source of crash, and its runtime representation to roc_panic.
pub const CrashOrigin = enum(u32) {
/// The crash is due to Roc, either via a builtin or type error.
Roc = 0,
/// The crash is user-defined.
User = 1,
};

pub const LowLevel = .{};

// TODO: move to relevant stages
pub const TypeVar = struct { id: u32 };
74 changes: 74 additions & 0 deletions src/base/env.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const std = @import("std");
const base = @import("../base.zig");
const cols = @import("../collections.zig");
const problem = @import("../problem.zig");

pub const ModuleEnv = struct {
symbols: base.SymbolStore,
modules: base.ModuleStore,
strings: cols.LargeStringInterner,
tag_names: cols.TagNameInterner,
tag_ids_for_slicing: cols.SafeList(cols.TagNameId),
field_names: cols.FieldNameInterner,
field_ids_for_slicing: cols.SafeList(cols.FieldNameId),
problems: cols.SafeList(problem.Problem),
// TODO: where are these used, and how do we manage them?
// pub tuple_elem_indices: Vec<usize>,
// pub record_fields: Vec<RecordField<()>>,

pub fn init(allocator: std.mem.Allocator) ModuleEnv {
return ModuleEnv{
.symbols = base.SymbolStore.init(allocator),
.modules = base.ModuleStore.init(allocator),
.strings = cols.LargeStringInterner.init(allocator),
.tag_names = cols.TagNameInterner.init(allocator),
.tag_ids_for_slicing = cols.SafeList(cols.TagNameId).init(allocator),
.field_names = cols.FieldNameInterner.init(allocator),
.field_ids_for_slicing = cols.SafeList(cols.FieldNameId).init(allocator),
.problems = cols.SafeList(problem.Problem).init(allocator),
};
}

pub fn deinit(self: *ModuleEnv) void {
self.symbols.deinit();
self.modules.deinit();
self.strings.deinit();
self.tag_names.deinit();
self.tag_ids_for_slicing.deinit();
self.field_names.deinit();
self.field_ids_for_slicing.deinit();
self.problems.deinit();
}

pub fn addTagNameSlice(
self: *ModuleEnv,
name_ids: []cols.TagNameId,
) cols.SafeList(cols.TagNameId).Slice {
return self.tag_ids_for_slicing.appendSlice(name_ids);
}

pub fn addFieldNameSlice(
self: *ModuleEnv,
name_ids: []cols.FieldNameId,
) cols.SafeList(cols.FieldNameId).Slice {
return self.field_ids_for_slicing.appendSlice(name_ids);
}
};

pub const GlobalEnv = struct {
// TODO: do we need this if each module manages this?
modules: base.ModuleStore,
packages: base.PackageStore,

pub fn init(allocator: std.mem.Allocator) GlobalEnv {
return GlobalEnv{
.modules = base.ModuleStore.init(allocator),
.packages = base.PackageStore.init(allocator),
};
}

pub fn deinit(self: *GlobalEnv) void {
self.modules.deinit();
self.packages.deinit();
}
};
75 changes: 75 additions & 0 deletions src/base/module.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
const std = @import("std");
const cols = @import("../collections.zig");

pub const ModuleId = struct { id: u32 };

pub const Module = struct {
name: []u8,
package_shorthand: ?[]u8,
is_builtin: bool,
};

pub const ModuleStore = struct {
modules: cols.SafeMultiList(Module),

pub fn init(allocator: std.mem.Allocator) ModuleStore {
const modules = cols.SafeMultiList(Module).init(allocator);
modules.append(Module{
.id = 0,
.name = &.{},
.base_name = &.{},
.package_shorthand = null,
.is_builtin = false,
});

// TODO: insert builtins automatically?

return ModuleStore{ .modules = modules };
}

pub fn deinit(self: *ModuleStore) void {
self.modules.deinit();
}

pub fn lookup(self: *ModuleStore, name: []const u8, package_shorthand: ?[]const u8) ?ModuleId {
const items = self.modules.items;

for (0..self.modules.len()) |index| {
const other_name = items.items(.name_segments)[index];
if (name == other_name) {
const other_package_shorthand = items.items(.package_shorthand)[index];
if (other_package_shorthand == package_shorthand) {
return ModuleId{ .id = @as(u32, index) };
}
}
}

return null;
}

pub fn getOrInsert(
self: *ModuleStore,
name: []const u8,
package_shorthand: ?[]const u8,
) ModuleId {
if (self.lookup(name, package_shorthand)) |id| {
return id;
} else {
const new_id = self.modules.insert(Module{
.name = name,
.package_shorthand = package_shorthand,
.is_builtin = false,
});

return ModuleId{ .id = new_id.id };
}
}

pub fn getName(self: *ModuleStore, id: ModuleId) []u8 {
return self.modules.items.items(.name)[@as(usize, id.id)];
}

pub fn getPackageShorthand(self: *ModuleStore, id: ModuleId) ?[]u8 {
return self.modules.items.items(.package_shorthand)[@as(usize, id.id)];
}
};
29 changes: 29 additions & 0 deletions src/base/package.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const std = @import("std");

pub const PackageId = struct { id: u32 };

pub const Package = struct {
id: PackageId,
/// The BLAKE3 hash of the tarball's contents. Also the .tar filename on disk.
content_hash: []u8,
/// On disk, this will be the subfolder inside the cache dir where the package lives
cache_subdir: []u8,
/// Other code will default this to main.roc, but this module isn't concerned with that default.
root_module_filename: ?[]u8,
};

pub const PackageStore = struct {
allocator: std.mem.Allocator,
packages: std.MultiArrayList(Package),

pub fn init(allocator: std.mem.Allocator) PackageStore {
return PackageStore{
.allocator = allocator,
.packages = std.MultiArrayList(Package),
};
}

pub fn deinit(self: *PackageStore) void {
self.packages.deinit();
}
};
70 changes: 70 additions & 0 deletions src/base/primitive.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const cols = @import("../collections.zig");

// TODO: figure out how to combine enums and union(enum)s at comptime
// to avoid them being multilevel

pub const Primitive = union(enum) {
Int: Int,
Float: Float,
Bool,
Str,
Crash,

pub const Int = enum {
U8,
I8,
U16,
I16,
U32,
I32,
U64,
I64,
U128,
I128,
};

pub const Float = enum {
F32,
F64,
Dec,
};

pub const Num = union(enum) {
Int: Int,
Float: Float,
};
};

pub const Literal = union(enum) {
Int: Int,
Float: Float,
Bool: bool,
Str: cols.LargeStringId,
Crash: cols.LargeStringId,

pub const Int = union(enum) {
I8: i8,
U8: u8,
I16: i16,
U16: u16,
I32: i32,
U32: u32,
I64: i64,
U64: u64,
I128: i128,
U128: u128,
};

pub const Float = union(enum) {
F32: f32,
F64: f64,
// We represent Dec as a large int divided by 10^18, which is the maximum
// number of decimal places that allows lossless conversion of U64 to Dec
Dec: u128,
};

pub const Num = union(enum) {
Int: Int,
Float: Float,
};
};
34 changes: 34 additions & 0 deletions src/base/region.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const std = @import("std");

pub const Region = struct {
start: Position,
end: Position,

pub fn format(self: *const Region, comptime fmt: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
if (fmt.len != 0) {
std.fmt.invalidFmtError(fmt, self);
}

if ((self.start == Position.zero()) and (self.end == Position.zero())) {
// In tests, it's super common to set all Located values to 0.
// Also in tests, we don't want to bother printing the locations
// because it makes failed assertions much harder to read.
return writer.print("…", .{});
} else {
return writer.print("@{}-{}", .{ self.start.offset, self.end.offset });
}
}
};

pub const Position = struct {
offset: u32,

pub fn zero() Position {
return Position{ .offset = 0 };
}
};

pub const LineAndColumn = packed struct(u32) {
line: u20,
column: u12,
};
Loading

0 comments on commit 5a4095a

Please sign in to comment.