diff --git a/src/compiler.zig b/src/compiler.zig index ae21e84..6695de9 100644 --- a/src/compiler.zig +++ b/src/compiler.zig @@ -167,6 +167,8 @@ pub const Compiler = struct { if (token_opt) |token| { self.parser.current = token; break; + } else { + self.errorCurrent(self.parser.current.lexeme); } } } @@ -219,12 +221,11 @@ pub const Compiler = struct { /// Emits bytecode for a number being loaded into the code. fn number(self: *Compiler) !void { - std.debug.warn("parsing number: '{}'\n", self.parser.previous.lexeme); var value: f64 = try std.fmt.parseFloat( f64, self.parser.previous.lexeme, ); - try self.emitConstant(values.NumberVal(value)); + try self.emitConstant(value); } /// Emits bytecode for a given unary. diff --git a/src/main.zig b/src/main.zig index 660a9e7..4611d6f 100644 --- a/src/main.zig +++ b/src/main.zig @@ -12,12 +12,12 @@ const InterpretResult = vm.InterpretResult; pub var hadError = false; -fn run(allocator: *Allocator, data: []u8) !void { +fn run(allocator: *Allocator, data: []u8) !InterpretResult { var stdout_file = try std.io.getStdOut(); const stdout = &stdout_file.outStream().stream; var vmach = try vm.VM.init(allocator, stdout, data, true); - try vmach.interpret(); + return try vmach.interpret(); } pub fn doError(line: usize, message: []const u8) !void { @@ -40,14 +40,9 @@ fn runFile(allocator: *Allocator, path: []const u8) !void { var slice = try allocator.alloc(u8, total_bytes); _ = try lox_file.read(slice); - run(allocator, slice) catch |err| { - switch (err) { - InterpretResult.Ok => {}, - InterpretResult.CompileError => std.os.exit(65), - InterpretResult.RuntimeError => std.os.exit(70), - else => return err, - } - }; + var res = try run(allocator, slice); + if (res == vm.InterpretResult.CompileError) std.os.exit(65); + if (res == vm.InterpretResult.RuntimeError) std.os.exit(70); } fn runPrompt(allocator: *Allocator) !void { @@ -64,15 +59,7 @@ fn runPrompt(allocator: *Allocator) !void { return err; }; - run(allocator, line) catch |err| { - switch (err) { - InterpretResult.Ok => {}, - InterpretResult.CompileError, InterpretResult.RuntimeError => blk: { - try stdout.print("compile/runtime error.\n"); - }, - else => return err, - } - }; + _ = try run(allocator, line); } } diff --git a/src/new_scanner.zig b/src/new_scanner.zig index 93f8160..0e2cbb0 100644 --- a/src/new_scanner.zig +++ b/src/new_scanner.zig @@ -147,8 +147,8 @@ pub const Scanner = struct { } fn peekNext(self: *Scanner) u8 { - if (self.current + 1 >= self.source.len) return 0; - return self.source[self.current + 1]; + if (self.isAtEnd()) return 0; + return self.source[self.current - 1]; } fn skipWhitespace(self: *Scanner) void { @@ -259,7 +259,6 @@ pub const Scanner = struct { while (self.peek() != '\n' and !self.isAtEnd()) { _ = self.advance(); } - break :blk null; } else { break :blk self.makeToken(.SLASH); diff --git a/src/value.zig b/src/value.zig index aa33ecc..b97d402 100644 --- a/src/value.zig +++ b/src/value.zig @@ -3,42 +3,10 @@ const std = @import("std"); const Allocator = std.mem.Allocator; // NOTE: right now, only numbers. - -pub const ValueType = enum(u8) { - Bool, - Nil, - Number, -}; - -pub const ValueValue = union(ValueType) { - Bool: bool, - Nil: void, - Number: f64, -}; - -pub const Value = struct { - vtype: ValueType, - as: ValueValue, -}; - -// helper functions -pub fn BoolVal(val: bool) Value { - return Value{ .vtype = .Bool, .as = ValueValue{ .Bool = val } }; -} - -pub fn NilVal() Value { - return Value{ .vtype = .Nil, .as = ValueValue{ .Nil = {} } }; -} - -pub fn NumberVal(val: f64) Value { - return Value{ .vtype = .Number, .as = ValueValue{ .Number = val } }; -} +pub const Value = f64; pub fn printValue(stdout: var, value: Value) !void { - switch (value.as) { - .Number => try stdout.print("{}", value.as.Number), - else => unreachable, - } + try stdout.print("{}", value); } pub const ValueList = struct { diff --git a/src/vm.zig b/src/vm.zig index 398f9ab..e58bc66 100644 --- a/src/vm.zig +++ b/src/vm.zig @@ -1,7 +1,6 @@ const std = @import("std"); const chunk = @import("chunk.zig"); const value = @import("value.zig"); -const values = value; const compiler = @import("compiler.zig"); const Chunk = chunk.Chunk; @@ -10,7 +9,7 @@ const Compiler = compiler.Compiler; pub const StdOut = *std.io.OutStream(std.fs.File.WriteError); -pub const InterpretResult = error{ +pub const InterpretResult = enum { Ok, CompileError, RuntimeError, @@ -92,50 +91,35 @@ pub const VM = struct { } /// gets a f64 out of a value on the top of the stack. - fn popNum(self: *VM) !f64 { - var val: Value = self.pop(); - - switch (val.vtype) { - .Number => return val.as.Number, - - else => |vtype| blk: { - self.runtimeError("Expected number, got {x}", vtype); - return InterpretResult.RuntimeError; - }, - } + fn popNum(self: *VM) f64 { + return self.pop(); } fn doAdd(self: *VM) !void { - var b = try self.popNum(); - var a = try self.popNum(); - try self.push(values.NumberVal(a + b)); + var b = self.popNum(); + var a = self.popNum(); + try self.push(a + b); } fn doSub(self: *VM) !void { - var b = try self.popNum(); - var a = try self.popNum(); - try self.push(values.NumberVal(a - b)); + var b = self.popNum(); + var a = self.popNum(); + try self.push(a * b); } fn doMul(self: *VM) !void { - var b = try self.popNum(); - var a = try self.popNum(); - try self.push(values.NumberVal(a * b)); + var b = self.popNum(); + var a = self.popNum(); + try self.push(a * b); } fn doDiv(self: *VM) !void { - var b = try self.popNum(); - var a = try self.popNum(); - try self.push(values.NumberVal(a / b)); + var b = self.popNum(); + var a = self.popNum(); + try self.push(a / b); } - fn runtimeError(self: *VM, comptime fmt: []const u8, args: ...) void { - std.debug.warn(fmt, args); - std.debug.warn("\n[line {}] in script\n", self.chk.lines[self.ip]); - self.resetStack(); - } - - fn run(self: *VM) !void { + fn run(self: *VM) !InterpretResult { while (true) { if (self.debug_flag) { try self.debugStack(); @@ -166,22 +150,7 @@ pub const VM = struct { chunk.OpCode.Subtract => try self.doSub(), chunk.OpCode.Multiply => try self.doMul(), chunk.OpCode.Divide => try self.doDiv(), - chunk.OpCode.Negate => blk: { - var val = self.peek(0); - if (val.vtype != .Bool) { - self.runtimeError("Operand must be a number."); - return InterpretResult.RuntimeError; - } - - val = self.pop(); - switch (val.as) { - .Number => |num| { - try self.push(values.NumberVal(-num)); - }, - else => unreachable, - } - }, - + chunk.OpCode.Negate => try self.push(-self.pop()), else => blk: { std.debug.warn("Unknown instruction: {x}\n", instruction); return InterpretResult.RuntimeError; @@ -190,7 +159,7 @@ pub const VM = struct { } } - pub fn interpret(self: *VM) !void { + pub fn interpret(self: *VM) !InterpretResult { //self.ip = 0; //self.debug("VM start\n"); //var res = try self.run(); @@ -227,8 +196,4 @@ pub const VM = struct { self.stackTop -= 1; return self.stack[self.stackTop]; } - - pub fn peek(self: *VM, distance: usize) Value { - return self.stack[self.stackTop - 1 - distance]; - } };