From 5f132c8422cb88e3f0ca266f4de9cc0129d44775 Mon Sep 17 00:00:00 2001 From: Baitinq Date: Sat, 8 Mar 2025 20:53:46 +0100 Subject: Feature: Add support for GT and LT operators --- examples/10.src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/10.src') diff --git a/examples/10.src b/examples/10.src index 0ec38ea..67199b0 100644 --- a/examples/10.src +++ b/examples/10.src @@ -1,7 +1,7 @@ let main = () => i64 { let counter = 0; - while !(counter == 10) { + while counter < 10 { print(counter); counter = counter + 1; }; -- cgit 1.4.1 From 7dda19a956a19aeaa25fc23d8815dac250b4ae8a Mon Sep 17 00:00:00 2001 From: Baitinq Date: Sun, 9 Mar 2025 00:46:07 +0100 Subject: Feature: Add support for mod operator --- examples/10.src | 2 +- grammar.ebnf | 2 +- src/codegen.zig | 14 ++++++++++---- src/evaluator.zig | 13 ++++++++++--- src/parser.zig | 26 +++++++++++++++++++------- src/tokenizer.zig | 2 ++ 6 files changed, 43 insertions(+), 16 deletions(-) (limited to 'examples/10.src') diff --git a/examples/10.src b/examples/10.src index 67199b0..b840849 100644 --- a/examples/10.src +++ b/examples/10.src @@ -6,7 +6,7 @@ let main = () => i64 { counter = counter + 1; }; - while counter == 0 { + while counter % 3 == 0 { print(0); }; diff --git a/grammar.ebnf b/grammar.ebnf index addd256..bbfe488 100644 --- a/grammar.ebnf +++ b/grammar.ebnf @@ -20,7 +20,7 @@ EqualityExpression ::= AdditiveExpression ("==" | "<" | ">") AdditiveExpression AdditiveExpression ::= MultiplicativeExpression (("+" | "-") MultiplicativeExpression)* -MultiplicativeExpression ::= UnaryExpression (("*" | "/") UnaryExpression)* +MultiplicativeExpression ::= UnaryExpression (("*" | "/" | "%") UnaryExpression)* UnaryExpression ::= ("!" | "-") UnaryExpression | PrimaryExpression diff --git a/src/codegen.zig b/src/codegen.zig index 1e9a33e..98b7c16 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -380,10 +380,16 @@ pub const CodeGen = struct { const rhs_value = try self.generate_expression_value(exp.rhs, null); var result: types.LLVMValueRef = undefined; - if (exp.multiplication) { - result = core.LLVMBuildMul(self.builder, lhs_value.value, rhs_value.value, "") orelse return CodeGenError.CompilationError; - } else { - result = core.LLVMBuildSDiv(self.builder, lhs_value.value, rhs_value.value, "") orelse return CodeGenError.CompilationError; + switch (exp.typ) { + .MUL => { + result = core.LLVMBuildMul(self.builder, lhs_value.value, rhs_value.value, "") orelse return CodeGenError.CompilationError; + }, + .DIV => { + result = core.LLVMBuildSDiv(self.builder, lhs_value.value, rhs_value.value, "") orelse return CodeGenError.CompilationError; + }, + .MOD => { + result = core.LLVMBuildSRem(self.builder, lhs_value.value, rhs_value.value, "") orelse return CodeGenError.CompilationError; + }, } return self.generate_literal(result, core.LLVMInt64Type(), name); diff --git a/src/evaluator.zig b/src/evaluator.zig index 43380a1..fef08a2 100644 --- a/src/evaluator.zig +++ b/src/evaluator.zig @@ -177,8 +177,11 @@ pub const Evaluator = struct { const lhs = try self.get_expression_value(x.lhs) orelse return EvaluatorError.EvaluationError; const rhs = try self.get_expression_value(x.rhs) orelse return EvaluatorError.EvaluationError; std.debug.assert(lhs.* == .NUMBER and rhs.* == .NUMBER); - if (x.multiplication) return try self.create_variable(.{ .NUMBER = lhs.NUMBER * rhs.NUMBER }); - return try self.create_variable(.{ .NUMBER = @divFloor(lhs.NUMBER, rhs.NUMBER) }); + switch (x.typ) { + .MUL => return try self.create_variable(.{ .NUMBER = lhs.NUMBER * rhs.NUMBER }), + .DIV => return try self.create_variable(.{ .NUMBER = @divFloor(lhs.NUMBER, rhs.NUMBER) }), + .MOD => return try self.create_variable(.{ .NUMBER = @rem(lhs.NUMBER, rhs.NUMBER) }), + } }, .UNARY_EXPRESSION => |x| { const val = try self.get_expression_value(x.expression) orelse return EvaluatorError.EvaluationError; @@ -193,7 +196,11 @@ pub const Evaluator = struct { const lhs = try self.get_expression_value(x.lhs) orelse return EvaluatorError.EvaluationError; const rhs = try self.get_expression_value(x.rhs) orelse return EvaluatorError.EvaluationError; std.debug.assert(lhs.* == .NUMBER and rhs.* == .NUMBER); //TODO: Generic - return try self.create_variable(.{ .BOOLEAN = (lhs.NUMBER == rhs.NUMBER) }); + switch (x.typ) { + .EQ => return try self.create_variable(.{ .BOOLEAN = (lhs.NUMBER == rhs.NUMBER) }), + .GT => return try self.create_variable(.{ .BOOLEAN = (lhs.NUMBER > rhs.NUMBER) }), + .LT => return try self.create_variable(.{ .BOOLEAN = (lhs.NUMBER < rhs.NUMBER) }), + } }, .PRIMARY_EXPRESSION => |x| { switch (x) { diff --git a/src/parser.zig b/src/parser.zig index ad2b8d0..b0a469c 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -37,9 +37,9 @@ pub const Node = union(enum) { rhs: *Node, }, MULTIPLICATIVE_EXPRESSION: struct { - multiplication: bool, lhs: *Node, rhs: *Node, + typ: MultiplicativeExpressionType, }, UNARY_EXPRESSION: struct { negation: bool, @@ -82,6 +82,12 @@ pub const EqualityExpressionType = enum { GT, }; +pub const MultiplicativeExpressionType = enum { + MUL, + DIV, + MOD, +}; + pub const Parser = struct { tokens: []tokenizer.Token, offset: u32, @@ -328,24 +334,30 @@ pub const Parser = struct { return lhs; } - // MultiplicativeExpression ::= UnaryExpression (("*" | "/") UnaryExpression)* + // MultiplicativeExpression ::= UnaryExpression (("*" | "/" | "%") UnaryExpression)* fn parse_multiplicative_expression(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing additive expression {any}\n", .{self.peek_token()}); var lhs = try self.parse_unary_expression(); while (true) { - const mul = self.accept_token(tokenizer.TokenType.MUL); - const div = self.accept_token(tokenizer.TokenType.DIV); - - if (mul == null and div == null) break; + var typ: MultiplicativeExpressionType = undefined; + if (self.accept_token(tokenizer.TokenType.MUL) != null) { + typ = .MUL; + } else if (self.accept_token(tokenizer.TokenType.DIV) != null) { + typ = .DIV; + } else if (self.accept_token(tokenizer.TokenType.MOD) != null) { + typ = .MOD; + } else { + break; + } const rhs = try self.parse_unary_expression(); lhs = try self.create_node(.{ .MULTIPLICATIVE_EXPRESSION = .{ - .multiplication = mul != null, .lhs = lhs, .rhs = rhs, + .typ = typ, } }); } diff --git a/src/tokenizer.zig b/src/tokenizer.zig index 99ed10d..f0dcd26 100644 --- a/src/tokenizer.zig +++ b/src/tokenizer.zig @@ -25,6 +25,7 @@ pub const TokenType = union(enum) { MINUS: void, MUL: void, DIV: void, + MOD: void, BANG: void, LESS: void, GREATER: void, @@ -85,6 +86,7 @@ pub const Tokenizer = struct { if (self.accept_string("-")) return self.create_token(.{ .MINUS = void{} }); if (self.accept_string("*")) return self.create_token(.{ .MUL = void{} }); if (self.accept_string("/")) return self.create_token(.{ .DIV = void{} }); + if (self.accept_string("%")) return self.create_token(.{ .MOD = void{} }); if (self.accept_string("!")) return self.create_token(.{ .BANG = void{} }); if (self.accept_string("<")) return self.create_token(.{ .LESS = void{} }); if (self.accept_string(">")) return self.create_token(.{ .GREATER = void{} }); -- cgit 1.4.1 From 21432e8965403975a3f8e9175a46430b7b818241 Mon Sep 17 00:00:00 2001 From: Baitinq Date: Sun, 9 Mar 2025 09:52:54 +0100 Subject: Codegen: Fix bug with if statements inside while loops --- examples/10.src | 8 +++++--- src/codegen.zig | 8 +++----- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'examples/10.src') diff --git a/examples/10.src b/examples/10.src index b840849..59f91e1 100644 --- a/examples/10.src +++ b/examples/10.src @@ -6,9 +6,11 @@ let main = () => i64 { counter = counter + 1; }; - while counter % 3 == 0 { - print(0); + while true { + if counter == 10 { + return counter; + }; }; - return counter; + return 1; }; diff --git a/src/codegen.zig b/src/codegen.zig index 98b7c16..45ebde6 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -203,7 +203,7 @@ pub const CodeGen = struct { for (if_statement.statements) |stmt| { try self.generate_statement(stmt); } - const merge_block = core.LLVMAppendBasicBlock(core.LLVMGetLastFunction(self.llvm_module), "else_block"); + const merge_block = core.LLVMAppendBasicBlock(core.LLVMGetLastFunction(self.llvm_module), "merge_block"); const last_instr = core.LLVMGetLastInstruction(then_block); if (core.LLVMIsATerminatorInst(last_instr) == null) { _ = core.LLVMBuildBr(self.builder, merge_block); @@ -233,10 +233,8 @@ pub const CodeGen = struct { for (while_statement.statements) |stmt| { try self.generate_statement(stmt); } - const last_instr = core.LLVMGetLastInstruction(inner_block); - if (core.LLVMIsATerminatorInst(last_instr) == null) { - _ = core.LLVMBuildBr(self.builder, while_block); - } + + _ = core.LLVMBuildBr(self.builder, while_block); core.LLVMPositionBuilderAtEnd(self.builder, outer_block); } -- cgit 1.4.1