Skip to content

Commit

Permalink
Compilation: Just use a HashMap for environment
Browse files Browse the repository at this point in the history
  • Loading branch information
ehaas committed Aug 14, 2023
1 parent 9f907ae commit 0ee9656
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 69 deletions.
70 changes: 11 additions & 59 deletions src/Compilation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -25,63 +25,10 @@ pub const Error = error{

pub const bit_int_max_bits = 128;

/// Environment variables used during compilation / linking.
pub const Environment = struct {
/// Directory to use for temporary files
/// TODO: not implemented yet
tmpdir: ?[]const u8 = null,

/// Directories to try when searching for subprograms.
/// TODO: not implemented yet
compiler_path: ?[]const u8 = null,

/// Directories to try when searching for special linker files, if compiling for the native target
/// TODO: not implemented yet
library_path: ?[]const u8 = null,

/// List of directories to be searched as if specified with -I, but after any paths given with -I options on the command line
/// Used regardless of the language being compiled
/// TODO: not implemented yet
cpath: ?[]const u8 = null,

/// List of directories to be searched as if specified with -I, but after any paths given with -I options on the command line
/// Used if the language being compiled is C
/// TODO: not implemented yet
c_include_path: ?[]const u8 = null,

/// UNIX timestamp to be used instead of the current date and time in the __DATE__ and __TIME__ macros
source_date_epoch: ?[]const u8 = null,

/// Load all of the environment variables using the std.process API. Do not use if using Aro as a shared library on Linux without libc
/// See https://github.com/ziglang/zig/issues/4524
/// Assumes that `self` has been default-initialized
pub fn loadAll(self: *Environment, allocator: std.mem.Allocator) !void {
errdefer self.deinit(allocator);

inline for (@typeInfo(@TypeOf(self.*)).Struct.fields) |field| {
std.debug.assert(@field(self, field.name) == null);

var env_var_buf: [field.name.len]u8 = undefined;
const env_var_name = std.ascii.upperString(&env_var_buf, field.name);
const val: ?[]const u8 = std.process.getEnvVarOwned(allocator, env_var_name) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
error.EnvironmentVariableNotFound => null,
error.InvalidUtf8 => null,
};
@field(self, field.name) = val;
}
}

/// Use this only if environment slices were allocated with `allocator` (such as via `loadAll`)
pub fn deinit(self: *Environment, allocator: std.mem.Allocator) void {
inline for (@typeInfo(@TypeOf(self.*)).Struct.fields) |field| {
if (@field(self, field.name)) |slice| {
allocator.free(slice);
}
}
self.* = undefined;
}
};
pub const Environment = std.HashMapUnmanaged([]const u8, []const u8, std.process.EnvMap.EnvNameHashContext, std.hash_map.default_max_load_percentage);
comptime {
assert(Environment == @TypeOf(std.process.EnvMap.init(undefined).hash_map.unmanaged));
}

gpa: Allocator,
environment: Environment = .{},
Expand Down Expand Up @@ -120,9 +67,10 @@ types: struct {
invalid_utf8_locs: std.AutoHashMapUnmanaged(Source.Id, u32) = .{},
string_interner: StringInterner = .{},

pub fn init(gpa: Allocator) Compilation {
pub fn initWithEnvironment(gpa: Allocator, environment: Environment) Compilation {
return .{
.gpa = gpa,
.environment = environment,
.sources = std.StringArrayHashMap(Source).init(gpa),
.diag = Diagnostics.init(gpa),
.include_dirs = std.ArrayList([]const u8).init(gpa),
Expand All @@ -132,6 +80,10 @@ pub fn init(gpa: Allocator) Compilation {
};
}

pub fn init(gpa: Allocator) Compilation {
return initWithEnvironment(gpa, .{});
}

pub fn deinit(comp: *Compilation) void {
for (comp.pragma_handlers.values()) |pragma| {
pragma.deinit(pragma, comp);
Expand All @@ -158,7 +110,7 @@ pub fn intern(comp: *Compilation, str: []const u8) !StringInterner.StringId {
}

pub fn getSourceEpoch(self: *const Compilation, max: i64) !?i64 {
const provided = self.environment.source_date_epoch orelse return null;
const provided = self.environment.get("SOURCE_DATE_EPOCH") orelse return null;
const parsed = std.fmt.parseInt(i64, provided, 10) catch return error.InvalidEpoch;
if (parsed < 0 or parsed > max) return error.InvalidEpoch;
return parsed;
Expand Down
19 changes: 14 additions & 5 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,26 @@ pub fn main() !u8 {
return 1;
};

var comp = Compilation.init(gpa);
defer comp.deinit();

comp.environment.loadAll(gpa) catch |er| switch (er) {
var env_map = std.process.getEnvMap(gpa) catch |er| switch (er) {
error.OutOfMemory => {
std.debug.print("out of memory\n", .{});
if (fast_exit) std.process.exit(1);
return 1;
},
};
defer comp.environment.deinit(gpa);
defer env_map.deinit();

var comp = Compilation.initWithEnvironment(gpa, env_map.hash_map.unmanaged);
defer comp.deinit();

// comp.environment.loadAll(gpa) catch |er| switch (er) {
// error.OutOfMemory => {
// std.debug.print("out of memory\n", .{});
// if (fast_exit) std.process.exit(1);
// return 1;
// },
// };
// defer comp.environment.deinit(gpa);

comp.addDefaultPragmaHandlers() catch |er| switch (er) {
error.OutOfMemory => {
Expand Down
9 changes: 4 additions & 5 deletions test/runner.zig
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ fn addCommandLineArgs(comp: *aro.Compilation, file: aro.Source, macro_buf: anyty
var parts = std.mem.splitScalar(u8, some, '=');
const name = parts.next().?;
const val = parts.next() orelse "";
inline for (@typeInfo(aro.Compilation.Environment).Struct.fields) |field| {
if (std.ascii.eqlIgnoreCase(name, field.name)) {
@field(comp.environment, field.name) = val;
}
}
try comp.environment.putNoClobber(comp.gpa, name, val);
}
}

Expand All @@ -47,6 +43,7 @@ fn addCommandLineArgs(comp: *aro.Compilation, file: aro.Source, macro_buf: anyty
fn testOne(allocator: std.mem.Allocator, path: []const u8) !void {
var comp = aro.Compilation.init(allocator);
defer comp.deinit();
defer comp.environment.deinit(comp.gpa);

try comp.addDefaultPragmaHandlers();
try comp.defineSystemIncludes();
Expand Down Expand Up @@ -149,6 +146,7 @@ pub fn main() !void {
// prepare compiler
var initial_comp = aro.Compilation.init(gpa);
defer initial_comp.deinit();
defer initial_comp.environment.deinit(gpa);

const cases_include_dir = try std.fs.path.join(gpa, &.{ args[1], "include" });
defer gpa.free(cases_include_dir);
Expand Down Expand Up @@ -182,6 +180,7 @@ pub fn main() !void {
comp.system_include_dirs = @TypeOf(comp.system_include_dirs).init(gpa);
comp.pragma_handlers = @TypeOf(comp.pragma_handlers).init(gpa);
// reset everything else
comp.environment.deinit(comp.gpa);
comp.deinit();
}

Expand Down

0 comments on commit 0ee9656

Please sign in to comment.