Compare commits

...

3 commits

Author SHA1 Message Date
aa94396e51 compiler: add nicer error handling
- vm: fix pop opcode handler
2019-06-02 18:11:23 -03:00
06df2d37ee add expression statements 2019-06-02 18:04:36 -03:00
bea6e34365 add print statement
- remove opcode return's use as debug
2019-06-02 17:28:54 -03:00
3 changed files with 74 additions and 3 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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();