diff --git a/src/chunk.zig b/src/chunk.zig index 50aca63..289ef33 100644 --- a/src/chunk.zig +++ b/src/chunk.zig @@ -25,6 +25,9 @@ const AllOpcodes = struct { pub Equal: u8 = 12, pub Greater: u8 = 13, pub Less: u8 = 14, + + pub Print: u8 = 15, + pub Pop: u8 = 16, }; pub const OpCode = AllOpcodes{}; @@ -189,6 +192,10 @@ pub const Chunk = struct { return try simpleInstruction(stdout, "OP_GREATER", index); } else if (instruction == OpCode.Less) { return try simpleInstruction(stdout, "OP_LESS", index); + } else if (instruction == OpCode.Print) { + return try simpleInstruction(stdout, "OP_PRINT", index); + } else if (instruction == OpCode.Pop) { + return try simpleInstruction(stdout, "OP_POP", index); } else { try stdout.print("Unknown opcode: {}\n", instruction); return index + 1; diff --git a/src/compiler.zig b/src/compiler.zig index 8666e11..71750da 100644 --- a/src/compiler.zig +++ b/src/compiler.zig @@ -186,6 +186,17 @@ pub const Compiler = struct { self.errorCurrent(msg); } + fn check(self: *Compiler, ttype: TokenType) bool { + return self.parser.current.ttype == ttype; + } + + fn match(self: *Compiler, ttype: TokenType) !bool { + if (!(self.check(ttype))) return false; + + try self.advance(); + return true; + } + fn currentChunk(self: *Compiler) *chunks.Chunk { return self.chunk; } @@ -314,14 +325,57 @@ pub const Compiler = struct { try self.parsePrecedence(.Assignment); } + fn printStmt(self: *Compiler) !void { + try self.expression(); + try self.consume(.SEMICOLON, "Expect ';' after value."); + try self.emitByte(OpCode.Print); + } + + fn exprStmt(self: *Compiler) !void { + try self.expression(); + try self.consume(.SEMICOLON, "Expect ';' after expression."); + try self.emitByte(OpCode.Pop); + } + + fn synchronize(self: *Compiler) !void { + self.parser.panicMode = false; + + while (self.parser.current.ttype != .EOF) { + if (self.parser.previous.ttype == .SEMICOLON) return; + + switch (self.parser.current.ttype) { + .CLASS, .FUN, .VAR, .FOR, .IF, .WHILE, .PRINT, .RETURN => return, + else => {}, + } + + try self.advance(); + } + } + + fn declaration(self: *Compiler) !void { + try self.statement(); + if (self.parser.panicMode) try self.synchronize(); + } + + fn statement(self: *Compiler) !void { + if (try self.match(.PRINT)) { + try self.printStmt(); + } else { + try self.exprStmt(); + } + } + /// Compile the source given when initializing the compiler /// into the given chunk. pub fn compile(self: *Compiler, chunk: *Chunk) !bool { self.scanr = try scanner.Scanner.init(self.allocator, self.src); try self.advance(); - try self.expression(); - try self.consume(.EOF, "Expect end of expression."); + while (!(try self.match(.EOF))) { + try self.declaration(); + } + // try self.expression(); + // try self.consume(.EOF, "Expect end of expression."); try self.end(); return !self.parser.hadError; diff --git a/src/vm.zig b/src/vm.zig index 197ba46..98211c6 100644 --- a/src/vm.zig +++ b/src/vm.zig @@ -240,9 +240,14 @@ pub const VM = struct { break :blk; }, - chunk.OpCode.Return => blk: { + chunk.OpCode.Print => blk: { try value.printValue(self.stdout, self.pop()); try self.stdout.print("\n"); + break :blk; + }, + + chunk.OpCode.Return => blk: { + // Exit VM return InterpretResult.Ok; }, @@ -250,6 +255,11 @@ pub const VM = struct { chunk.OpCode.True => try self.push(values.BoolVal(true)), chunk.OpCode.False => try self.push(values.BoolVal(false)), + chunk.OpCode.Pop => blk: { + _ = self.pop(); + break :blk; + }, + chunk.OpCode.Equal => blk: { var a = self.pop(); var b = self.pop();