diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Lexer.zig | 3 | ||||
-rw-r--r-- | src/compile.zig | 7 | ||||
-rw-r--r-- | src/parse.zig | 28 |
3 files changed, 30 insertions, 8 deletions
diff --git a/src/Lexer.zig b/src/Lexer.zig index 64457bf..9be99aa 100644 --- a/src/Lexer.zig +++ b/src/Lexer.zig @@ -29,6 +29,7 @@ pub const Token = struct { @"else", @"while", proc, + @"return", }; }; @@ -144,7 +145,7 @@ fn identifierOrKeyword(self: *Self) Token { } const value = self.source[self.start..self.pos]; return self.create(switch (std.meta.stringToEnum(Token.Type, value) orelse .invalid) { - .@"if", .@"else", .@"while", .proc => |t| t, + .@"if", .@"else", .@"while", .proc, .@"return" => |t| t, else => .identifier, }); } diff --git a/src/compile.zig b/src/compile.zig index 8c734c7..0ce170c 100644 --- a/src/compile.zig +++ b/src/compile.zig @@ -597,6 +597,13 @@ const ProcedureContext = struct { _ = proc; return error.CannotDefineProcedureHere; }, + .@"return" => |ret| { + const val = try self.compileExpr(ret.value); + try self.addInstr(.{ + .loc = expr.loc, + .type = .{ .ret = .{ .val = val } }, + }); + }, } return dest; } diff --git a/src/parse.zig b/src/parse.zig index 3ecb93b..d8b4d15 100644 --- a/src/parse.zig +++ b/src/parse.zig @@ -109,6 +109,7 @@ pub const Expr = struct { identifier, @"if": If, proc: Proc, + @"return": Return, pub const BinOp = struct { lhs: *const Expr, @@ -153,6 +154,10 @@ pub const Expr = struct { body: Block, param: ?Location, }; + + pub const Return = struct { + value: *const Expr, + }; }; fn format(self: Expr, writer: anytype, source: []const u8, indent: usize) !void { @@ -174,9 +179,8 @@ pub const Expr = struct { try writer.print(" else {}", .{fmt(@"else", source, indent)}); } }, - .proc => |proc| { - try writer.print("proc() {}", .{fmt(proc.body, source, indent)}); - }, + .proc => |proc| try writer.print("proc() {}", .{fmt(proc.body, source, indent)}), + .@"return" => |ret| try writer.print("return {}", .{fmt(ret.value, source, indent)}), } } }; @@ -186,7 +190,7 @@ const ParseError = error{ ExpectedRightParen, UnexpectedToken, InvalidAssignTarget, - ExprStatementMustBeCallOrIf, + InvalidExprStatement, }; pub fn file(allocator: Allocator, lexer: *Lexer) !File { @@ -258,8 +262,8 @@ fn parseStatement(allocator: Allocator, lexer: *Lexer) ParseError!Stmt { .loc = lhs.loc.combine(value.loc), .type = .{ .assign_var = .{ .ident = lhs.loc, .is_decl = colon != null, .value = value } }, }; - } else if (lhs.type != .call and lhs.type != .@"if") { - return error.ExprStatementMustBeCallOrIf; + } else if (lhs.type != .call and lhs.type != .@"if" and lhs.type != .@"return") { + return error.InvalidExprStatement; } return .{ .loc = lhs.loc, @@ -270,7 +274,17 @@ fn parseStatement(allocator: Allocator, lexer: *Lexer) ParseError!Stmt { } fn expression(allocator: Allocator, lexer: *Lexer) ParseError!*Expr { - return parseProc(allocator, lexer); + return parseReturn(allocator, lexer); +} + +fn parseReturn(allocator: Allocator, lexer: *Lexer) ParseError!*Expr { + if (lexer.peek().type != .@"return") return parseProc(allocator, lexer); + const ret = try mustEat(lexer, .@"return"); + const val = try parseProc(allocator, lexer); + return allocate(Expr, allocator, .{ + .loc = ret.loc.combine(val.loc), + .type = .{ .@"return" = .{ .value = val } }, + }); } fn parseProc(allocator: Allocator, lexer: *Lexer) ParseError!*Expr { |