Skip to content

Commit

Permalink
Start working through memory safety
Browse files Browse the repository at this point in the history
  • Loading branch information
booniepepper committed Jul 31, 2023
1 parent 937c374 commit 2839b81
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 8 deletions.
106 changes: 101 additions & 5 deletions src/builtins.zig
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,15 @@ pub fn quit(dt: *DtMachine) !void {
std.os.exit(0);
}

test "drop quit" {
const dt = @import("tests/dt_test_utils.zig").dt;

var res = try dt(&.{ "drop", "quit" });
try std.testing.expectEqualStrings("", res.stdout);
try std.testing.expectEqualStrings("", res.stderr);
try std.testing.expectEqual(@as(u8, 0), res.term.Exited);
}

pub fn exit(dt: *DtMachine) !void {
const log = std.log.scoped(.exit);

Expand All @@ -166,15 +175,45 @@ pub fn exit(dt: *DtMachine) !void {
std.os.exit(code);
}

test "7 exit" {
const dt = @import("tests/dt_test_utils.zig").dt;

var res = try dt(&.{ "7", "exit" });
try std.testing.expectEqualStrings("", res.stdout);
try std.testing.expectEqualStrings("", res.stderr);
try std.testing.expectEqual(@as(u8, 7), res.term.Exited);
}

pub fn version(dt: *DtMachine) !void {
try dt.push(.{ .string = main.version });
}

test "version" {
var dt = try DtMachine.init(std.testing.allocator);
defer dt.deinit();

try version(&dt);
var v = try dt.pop();

try std.testing.expect(v.isString());
}

pub fn cwd(dt: *DtMachine) !void {
const theCwd = try std.process.getCwdAlloc(dt.alloc);
try dt.push(.{ .string = theCwd });
}

test "cwd" {
var dt = try DtMachine.init(std.testing.allocator);
defer dt.deinit();

try cwd(&dt);
var dir = try dt.pop();
defer std.testing.allocator.free(dir.string);

try std.testing.expect(dir.isString());
}

pub fn cd(dt: *DtMachine) !void {
const log = std.log.scoped(.cd);

Expand All @@ -189,8 +228,18 @@ pub fn cd(dt: *DtMachine) !void {
std.os.chdir(path) catch |e| return dt.rewind(log, val, e);
}

test "\".\" cd" {
var dt = try DtMachine.init(std.testing.allocator);
defer dt.deinit();

try dt.push(.{ .string = "." });
try cd(&dt);
}

pub fn ls(dt: *DtMachine) !void {
const theCwd = try std.process.getCwdAlloc(dt.alloc);
defer dt.alloc.free(theCwd);

var dir = try std.fs.openIterableDirAbsolute(theCwd, .{});
var entries = dir.iterate();

Expand All @@ -205,6 +254,21 @@ pub fn ls(dt: *DtMachine) !void {
dir.close();
}

test "ls" {
var dt = try DtMachine.init(std.testing.allocator);
defer dt.deinit();

try ls(&dt);
const filesVal = try dt.pop();
const files = try filesVal.intoQuote(&dt);
defer files.deinit();

for (files.items) |file| {
try std.testing.expect(file.isString());
std.testing.allocator.free(file.string);
}
}

pub fn readf(dt: *DtMachine) !void {
const log = std.log.scoped(.readf);

Expand All @@ -213,6 +277,7 @@ pub fn readf(dt: *DtMachine) !void {

// We get a Dir from CWD so we can resolve relative paths
const theCwdPath = try std.process.getCwdAlloc(dt.alloc);
defer dt.alloc.free(theCwdPath);
var theCwd = try std.fs.openDirAbsolute(theCwdPath, .{});

var contents = _readf(dt, log, theCwd, filename) catch |e| {
Expand All @@ -239,6 +304,20 @@ fn _readf(dt: *DtMachine, log: anytype, dir: std.fs.Dir, filename: []const u8) !
return try file.readToEndAlloc(dt.alloc, std.math.pow(usize, 2, 16));
}

test "\"src/inspiration\" readf" {
var dt = try DtMachine.init(std.testing.allocator);
defer dt.deinit();

try dt.push(.{ .string = "src/inspiration" });
try readf(&dt);
var contents = try dt.pop();

try std.testing.expect(contents.isString());
try std.testing.expect(contents.string.len > 0);

std.testing.allocator.free(contents.string);
}

pub fn writef(dt: *DtMachine) !void {
const log = std.log.scoped(.writef);

Expand Down Expand Up @@ -280,30 +359,47 @@ pub fn exec(dt: *DtMachine) !void {
const childProcess = try val.intoString(dt);
var childArgs = std.mem.splitAny(u8, childProcess, " \t");
var argv = ArrayList([]const u8).init(dt.alloc);
defer argv.deinit();

while (childArgs.next()) |arg| try argv.append(arg);

var result = std.process.Child.exec(.{
.allocator = dt.alloc,
.argv = try argv.toOwnedSlice(),
.argv = argv.items,
}) catch |e| return dt.rewind(log, val, e);

switch (result.term) {
.Exited => |code| if (code == 0) {
const trimmed = std.mem.trimRight(u8, result.stdout, "\r\n");
try dt.push(.{ .string = trimmed });
dt.alloc.free(result.stderr);
try dt.push(.{ .string = result.stdout });
return;
},
else => {
try dt.red();
log.warn("{s}", .{result.stderr});
try dt.norm();

dt.alloc.free(result.stdout);
dt.alloc.free(result.stderr);

try dt.push(.{ .bool = false });
},
}
}

test "\"echo hi\" exec" {
var dt = try DtMachine.init(std.testing.allocator);
defer dt.deinit();

try dt.push(.{ .string = "echo hi" });
try exec(&dt);

const res = try dt.pop();
try std.testing.expect(res.isString());
try std.testing.expectEqualStrings("hi\n", res.string);
std.testing.allocator.free(res.string);
}

pub fn @"def!"(dt: *DtMachine) !void {
const log = std.log.scoped(.@"def!");

Expand Down Expand Up @@ -1250,6 +1346,6 @@ pub fn @"to-quote"(dt: *DtMachine) !void {
}

pub fn inspire(dt: *DtMachine) !void {
const i = std.crypto.random.uintLessThan(usize, dt.inspiration.len);
try dt.push(.{ .string = dt.inspiration[i] });
const i = std.crypto.random.uintLessThan(usize, dt.inspiration.items.len);
try dt.push(.{ .string = dt.inspiration.items[i] });
}
18 changes: 15 additions & 3 deletions src/interpret.zig
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub const DtMachine = struct {
stdoutConfig: std.io.tty.Config,
stderrConfig: std.io.tty.Config,

inspiration: []String,
inspiration: ArrayList(String),

pub fn init(alloc: Allocator) !DtMachine {
var nest = Stack(Quote){};
Expand All @@ -70,10 +70,22 @@ pub const DtMachine = struct {
.defs = Dictionary.init(alloc),
.stdoutConfig = std.io.tty.detectConfig(std.io.getStdOut()),
.stderrConfig = std.io.tty.detectConfig(std.io.getStdErr()),
.inspiration = inspirations.items,
.inspiration = inspirations,
};
}

pub fn deinit(self: *DtMachine) void {
self.defs.deinit();
self.inspiration.deinit();

var node = self.nest.first;
while (node) |n| {
node = n.next;
n.data.deinit();
self.alloc.destroy(n);
}
}

pub fn interpret(self: *DtMachine, tok: Token) !void {
switch (tok) {
.term => |cmdName| try self.handleCmd(cmdName),
Expand Down Expand Up @@ -358,7 +370,7 @@ pub const DtVal = union(enum) {

pub fn intoQuote(self: DtVal, state: *DtMachine) !Quote {
return switch (self) {
.quote => |q| _deepClone(q, state),
.quote => |q| q,
else => {
var q = Quote.init(state.alloc);
try q.append(self);
Expand Down

0 comments on commit 2839b81

Please sign in to comment.