Skip to content

Commit

Permalink
feat(repl): If user input ends with lone expression, get it and dump it
Browse files Browse the repository at this point in the history
  • Loading branch information
giann committed Oct 21, 2023
1 parent ed65219 commit dc5d707
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 7 deletions.
6 changes: 6 additions & 0 deletions src/node.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3814,6 +3814,12 @@ pub const FunctionNode = struct {
try codegen.emitOpCode(node.location, .OP_RETURN);
codegen.current.?.return_emitted = true;
}
} else if (function_type == .Repl and self.body != null and self.body.?.statements.items.len > 0 and self.body.?.statements.getLast().node_type == .Expression) {
// Repl and last expression is a lone statement, remove OP_POP, add OP_RETURN
assert(VM.getCode(codegen.current.?.function.?.chunk.code.pop()) == .OP_POP);
_ = codegen.current.?.function.?.chunk.lines.pop();

try codegen.emitReturn(node.location);
} else if (codegen.current.?.function.?.type_def.resolved_type.?.Function.return_type.def_type == .Void and !codegen.current.?.return_emitted) {
// TODO: detect if some branches of the function body miss a return statement
try codegen.emitReturn(node.location);
Expand Down
25 changes: 19 additions & 6 deletions src/repl.zig
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ pub fn repl(allocator: std.mem.Allocator) !void {
_ = ln.linenoiseHistoryLoad("./buzz_history");

// Import std and debug as commodity
runSource(
_ = runSource(
"import \"std\"; import \"debug\";",
"REPL",
&vm,
Expand All @@ -151,17 +151,19 @@ pub fn repl(allocator: std.mem.Allocator) !void {
_ = ln.linenoiseHistorySave("./buzz_history");

if (source.len > 0) {
runSource(
const expr = runSource(
source,
"REPL",
&vm,
&codegen,
&parser,
&gc,
) catch |err| {
) catch |err| failed: {
if (BuildOptions.debug) {
stderr.print("Failed with error {}\n", .{err}) catch unreachable;
}

break :failed null;
};

if (!parser.reporter.had_error and !codegen.reporter.had_error) {
Expand All @@ -182,15 +184,17 @@ pub fn repl(allocator: std.mem.Allocator) !void {
previous_type_registry = try gc.type_registry.registry.clone();

// Dump top of stack
if (previous_global_top != vm.globals_count) {
if (previous_global_top != vm.globals_count or expr != null) {
previous_global_top = vm.globals_count;

const value = expr orelse vm.globals.items[previous_global_top];

var value_str = std.ArrayList(u8).init(vm.gc.allocator);
defer value_str.deinit();
var state = DumpState.init(&vm);

state.valueDump(
vm.globals.items[previous_global_top],
value,
value_str.writer(),
false,
);
Expand Down Expand Up @@ -233,7 +237,7 @@ fn runSource(
codegen: *CodeGen,
parser: *Parser,
gc: *GarbageCollector,
) !void {
) !?Value {
var total_timer = std.time.Timer.start() catch unreachable;
var timer = try std.time.Timer.start();
var parsing_time: u64 = undefined;
Expand All @@ -253,6 +257,13 @@ fn runSource(
null,
);

// Does the user code ends with a lone expression?
const fnode = FunctionNode.cast(function_node).?;
const last_statement = fnode.body.?.statements.getLastOrNull();
if (last_statement != null and last_statement.?.node_type == .Expression) {
return vm.pop();
}

running_time = timer.read();
} else {
return CompileError.Recoverable;
Expand Down Expand Up @@ -285,6 +296,8 @@ fn runSource(
} else {
return CompileError.Recoverable;
}

return null;
}

const DumpState = struct {
Expand Down
4 changes: 3 additions & 1 deletion src/vm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1584,7 +1584,9 @@ pub const VM = struct {
}

// We're not in a fiber, the program is over
_ = self.pop();
if (self.flavor != .Repl) {
_ = self.pop();
}
return true;
}

Expand Down

0 comments on commit dc5d707

Please sign in to comment.