about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBaitinq <[email protected]>2025-03-09 00:46:07 +0100
committerBaitinq <[email protected]>2025-03-09 00:46:07 +0100
commit7dda19a956a19aeaa25fc23d8815dac250b4ae8a (patch)
treee84d34665c922b4babc23837a6549a79ab9c9d1c
parentFeature: Add support for GT and LT operators (diff)
downloadpry-lang-7dda19a956a19aeaa25fc23d8815dac250b4ae8a.tar.gz
pry-lang-7dda19a956a19aeaa25fc23d8815dac250b4ae8a.tar.bz2
pry-lang-7dda19a956a19aeaa25fc23d8815dac250b4ae8a.zip
Feature: Add support for mod operator
-rw-r--r--examples/10.src2
-rw-r--r--grammar.ebnf2
-rw-r--r--src/codegen.zig14
-rw-r--r--src/evaluator.zig13
-rw-r--r--src/parser.zig26
-rw-r--r--src/tokenizer.zig2
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{} });