diff options
| author | Baitinq <[email protected]> | 2025-03-09 00:46:07 +0100 |
|---|---|---|
| committer | Baitinq <[email protected]> | 2025-03-09 00:46:07 +0100 |
| commit | 7dda19a956a19aeaa25fc23d8815dac250b4ae8a (patch) | |
| tree | e84d34665c922b4babc23837a6549a79ab9c9d1c | |
| parent | Feature: Add support for GT and LT operators (diff) | |
| download | pry-lang-7dda19a956a19aeaa25fc23d8815dac250b4ae8a.tar.gz pry-lang-7dda19a956a19aeaa25fc23d8815dac250b4ae8a.tar.bz2 pry-lang-7dda19a956a19aeaa25fc23d8815dac250b4ae8a.zip | |
Feature: Add support for mod operator
| -rw-r--r-- | examples/10.src | 2 | ||||
| -rw-r--r-- | grammar.ebnf | 2 | ||||
| -rw-r--r-- | src/codegen.zig | 14 | ||||
| -rw-r--r-- | src/evaluator.zig | 13 | ||||
| -rw-r--r-- | src/parser.zig | 26 | ||||
| -rw-r--r-- | src/tokenizer.zig | 2 |
6 files changed, 43 insertions, 16 deletions
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{} }); |