Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions examples/division.sub
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
bind _ = print_str("69.420 / 2.0) == ",) in
bind _a = print_float(69.420 / 2.0,) in
bind _b = print_str(" ======= (420 / 69) == ",) in
print_int(420 / 69,)
;
26 changes: 21 additions & 5 deletions src/eval.zig
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub fn sema(program: Expr, ctx: Context) void {
},
.arith => |arith_expr| {
switch (arith_expr) {
.plus, .minus, .prod => |expr| {
.plus, .minus, .prod, .div => |expr| {
sema(expr.lhs.*, ctx);
sema(expr.rhs.*, ctx);
},
Expand Down Expand Up @@ -166,7 +166,7 @@ fn add_structs(program: Expr, ctx: *Context) !void {
switch (program.as) {
.arith => |expr| {
switch (expr) {
.plus, .minus, .prod => |arith_expr| {
.plus, .minus, .prod, .div => |arith_expr| {
try add_structs(arith_expr.lhs.*, ctx);
try add_structs(arith_expr.rhs.*, ctx);
},
Expand Down Expand Up @@ -401,7 +401,7 @@ fn eval_arith(expr: ArithExpr, ctx: Context, local_vars: *Vars, cursor: Cursor)
.cursor = cursor,
.file_path = ctx.file_path,
},
.prod, .minus, .plus => |op| {
.prod, .div, .minus, .plus => |op| {
const lhs = eval(op.lhs.*, ctx, local_vars);
const rhs = eval(op.rhs.*, ctx, local_vars);

Expand All @@ -421,6 +421,14 @@ fn eval_arith(expr: ArithExpr, ctx: Context, local_vars: *Vars, cursor: Cursor)
.cursor = cursor,
.file_path = ctx.file_path,
},
.div => .{
.as = .{ .arith = .{
.int = @divFloor(lhs.as.arith.int, rhs.as.arith.int),
} },
.content = ctx.content,
.cursor = cursor,
.file_path = ctx.file_path,
},
.plus => .{
.as = .{ .arith = .{
.int = lhs.as.arith.int + rhs.as.arith.int,
Expand All @@ -437,7 +445,7 @@ fn eval_arith(expr: ArithExpr, ctx: Context, local_vars: *Vars, cursor: Cursor)
.cursor = cursor,
.file_path = ctx.file_path,
},
else => unreachable,
.float, .int => unreachable,
};
} else if (lhs.as.arith == .float) {
return switch (expr) {
Expand All @@ -449,6 +457,14 @@ fn eval_arith(expr: ArithExpr, ctx: Context, local_vars: *Vars, cursor: Cursor)
.cursor = cursor,
.file_path = ctx.file_path,
},
.div => .{
.as = .{ .arith = .{
.float = lhs.as.arith.float / rhs.as.arith.float,
} },
.content = ctx.content,
.cursor = cursor,
.file_path = ctx.file_path,
},
.plus => .{
.as = .{ .arith = .{
.float = lhs.as.arith.float + rhs.as.arith.float,
Expand All @@ -465,7 +481,7 @@ fn eval_arith(expr: ArithExpr, ctx: Context, local_vars: *Vars, cursor: Cursor)
.cursor = cursor,
.file_path = ctx.file_path,
},
else => unreachable,
.float, .int => unreachable,
};
} else unreachable;
},
Expand Down
3 changes: 3 additions & 0 deletions src/expression.zig
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ pub const IfExpr = struct {

const ArithTag = enum {
prod,
div,
minus,
plus,
int,
Expand All @@ -441,6 +442,7 @@ pub const ArithExpr = union(ArithTag) {
const Self = @This();

prod: BinOp,
div: BinOp,
minus: BinOp,
plus: BinOp,
int: i32,
Expand All @@ -449,6 +451,7 @@ pub const ArithExpr = union(ArithTag) {
pub fn print(self: Self) void {
switch (self) {
.prod => |expr| expr.print("*"),
.div => |expr| expr.print("/"),
.minus => |expr| expr.print("-"),
.plus => |expr| expr.print("+"),
.int => |expr| std.debug.print("{}", .{expr}),
Expand Down
20 changes: 18 additions & 2 deletions src/lexer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ pub const Lexer = struct {

fn set_token(l: *Lexer, token: TokenKind) void {
switch (token) {
.minus, .prod, .plus => |t| {
.minus, .prod, .div, .plus => |t| {
l.token = t;
l.tokenType = .arith_op;
},
Expand Down Expand Up @@ -224,6 +224,11 @@ pub const Lexer = struct {
l.set_token(.prod);
return true;
},
'/' => {
l.clear_append_symbol(x);
l.set_token(.div);
return true;
},
'+' => {
l.clear_append_symbol(x);
l.set_token(.plus);
Expand Down Expand Up @@ -433,6 +438,7 @@ const TokenKind = enum {
minus,
plus,
prod,
div,

// parentheses
oparen,
Expand Down Expand Up @@ -474,6 +480,7 @@ const TokenKind = enum {
.minus => "-",
.plus => "+",
.prod => "*",
.div => "/",
.oparen => "(",
.cparen => ")",
.obrace => "{",
Expand Down Expand Up @@ -802,7 +809,7 @@ test "lex empty input and end token" {

test "lex arithmetic operators and punctuation" {
const source_code =
\\ (1 + 2) * 3 - 4,
\\ (1 + 2) * 3 - 4 / 25,
;
var l = Lexer.init(source_code, "test.zig");

Expand Down Expand Up @@ -842,6 +849,15 @@ test "lex arithmetic operators and punctuation" {
try expectEqual(4, l.integer_value);
try expectEqual(.int, l.token);

l.nexti();
try expectStrings("/", l.name.as_str(l.content));
try expectEqual(.div, l.token);

l.nexti();
try expectStrings("25", l.name.as_str(l.content));
try expectEqual(25, l.integer_value);
try expectEqual(.int, l.token);

l.nexti();
try expectStrings(",", l.name.as_str(l.content));
try expectEqual(.comma, l.token);
Expand Down
31 changes: 31 additions & 0 deletions src/parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ pub const Parser = struct {
if (op_token_type == .arith_op) {
const op: ArithExpr = switch (op_token) {
.prod => .{ .prod = .{ .lhs = lhs, .rhs = rhs } },
.div => .{ .div = .{ .lhs = lhs, .rhs = rhs } },
.plus => .{ .plus = .{ .lhs = lhs, .rhs = rhs } },
.minus => .{ .minus = .{ .lhs = lhs, .rhs = rhs } },
else => unreachable,
Expand Down Expand Up @@ -691,3 +692,33 @@ test "parse float addition" {
try expect(.float, rhs.as.arith.tag());
try expect(0.0, rhs.as.arith.float);
}

test "parse float division" {
var arena = arena_alloc();
defer arena.deinit();
const alloc = arena.allocator();

const source_code =
\\ 123.45 / 2.0;
;
var lexer = Lexer.init(source_code, "test.zig");
var parser = Parser.init(&lexer, alloc);
const expr = try parser.parse();

try expect(.list, expr.tag());
try expect(1, expr.as.list.items.len);

const plus_expr = expr.as.list.items[0];
try expect(.arith, plus_expr.tag());
try expect(.div, plus_expr.as.arith.tag());

const lhs = plus_expr.as.arith.div.lhs;
try expect(.arith, lhs.tag());
try expect(.float, lhs.as.arith.tag());
try expect(123.45, lhs.as.arith.float);

const rhs = plus_expr.as.arith.div.rhs;
try expect(.arith, rhs.tag());
try expect(.float, rhs.as.arith.tag());
try expect(2.0, rhs.as.arith.float);
}
Loading