diff options
| author | Baitinq <[email protected]> | 2025-03-08 20:53:46 +0100 |
|---|---|---|
| committer | Baitinq <[email protected]> | 2025-03-08 20:53:46 +0100 |
| commit | 5f132c8422cb88e3f0ca266f4de9cc0129d44775 (patch) | |
| tree | ab4acc5dbed602b19c4eea4e451175f4fa265200 | |
| parent | Codegen: Fix bug with recursive functions as variables (diff) | |
| download | pry-lang-5f132c8422cb88e3f0ca266f4de9cc0129d44775.tar.gz pry-lang-5f132c8422cb88e3f0ca266f4de9cc0129d44775.tar.bz2 pry-lang-5f132c8422cb88e3f0ca266f4de9cc0129d44775.zip | |
Feature: Add support for GT and LT operators
| -rw-r--r-- | examples/10.src | 2 | ||||
| -rw-r--r-- | grammar.ebnf | 2 | ||||
| -rw-r--r-- | src/codegen.zig | 84 | ||||
| -rw-r--r-- | src/parser.zig | 35 | ||||
| -rw-r--r-- | src/tokenizer.zig | 4 |
5 files changed, 47 insertions, 80 deletions
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; }; diff --git a/grammar.ebnf b/grammar.ebnf index ed87d7f..addd256 100644 --- a/grammar.ebnf +++ b/grammar.ebnf @@ -16,7 +16,7 @@ FunctionArguments ::= Expression ("," Expression)* Expression ::= EqualityExpression | AdditiveExpression -EqualityExpression ::= AdditiveExpression "==" AdditiveExpression +EqualityExpression ::= AdditiveExpression ("==" | "<" | ">") AdditiveExpression AdditiveExpression ::= MultiplicativeExpression (("+" | "-") MultiplicativeExpression)* diff --git a/src/codegen.zig b/src/codegen.zig index 9e06c8a..1e9a33e 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -307,6 +307,7 @@ pub const CodeGen = struct { try self.generate_statement(stmt); } + // TODO: This should be done with a defer when `builder_pos` is declared, but for some reason it doesn't work core.LLVMPositionBuilderAtEnd(self.builder, builder_pos); // Global functions @@ -358,18 +359,7 @@ pub const CodeGen = struct { } const loaded = core.LLVMBuildLoad2(self.builder, param_type, variable.value, ""); - if (name != null) { - const ptr = self.environment.get_variable(name.?).?; - _ = core.LLVMBuildStore(self.builder, loaded, ptr.value); - ptr.type = variable.type; - return ptr; - } - - return try self.create_variable(.{ - .value = loaded, - .type = variable.type, - .stack_level = null, - }); + return self.generate_literal(loaded, variable.type, name); }, }, .ADDITIVE_EXPRESSION => |exp| { @@ -383,19 +373,7 @@ pub const CodeGen = struct { result = core.LLVMBuildSub(self.builder, lhs_value.value, rhs_value.value, "") orelse return CodeGenError.CompilationError; } - if (name != null) { - const ptr = self.environment.get_variable(name.?) orelse unreachable; - _ = core.LLVMBuildStore(self.builder, result, ptr.value); - ptr.type = core.LLVMInt64Type(); - - return ptr; - } else { - return try self.create_variable(.{ - .value = result, - .type = core.LLVMInt64Type(), - .stack_level = null, - }); - } + return self.generate_literal(result, core.LLVMInt64Type(), name); }, .MULTIPLICATIVE_EXPRESSION => |exp| { const lhs_value = try self.generate_expression_value(exp.lhs, null); @@ -408,19 +386,7 @@ pub const CodeGen = struct { result = core.LLVMBuildSDiv(self.builder, lhs_value.value, rhs_value.value, "") orelse return CodeGenError.CompilationError; } - if (name != null) { - const ptr = self.environment.get_variable(name.?) orelse unreachable; - _ = core.LLVMBuildStore(self.builder, result, ptr.value); - ptr.type = core.LLVMInt64Type(); - - return ptr; - } else { - return try self.create_variable(.{ - .value = result, - .type = core.LLVMInt64Type(), - .stack_level = null, - }); - } + return self.generate_literal(result, core.LLVMInt64Type(), name); }, .UNARY_EXPRESSION => |exp| { const k = try self.generate_expression_value(exp.expression, null); @@ -439,48 +405,26 @@ pub const CodeGen = struct { }, } - if (name != null) { - const ptr = self.environment.get_variable(name.?) orelse unreachable; - - _ = core.LLVMBuildStore(self.builder, r, ptr.value); - ptr.type = t; - - return ptr; - } else { - return try self.create_variable(.{ - .value = r, - .type = t, - .stack_level = null, - }); - } + return self.generate_literal(r, t, name); }, .EQUALITY_EXPRESSION => |exp| { const lhs_value = try self.generate_expression_value(exp.lhs, null); const rhs_value = try self.generate_expression_value(exp.rhs, null); - const cmp = core.LLVMBuildICmp(self.builder, types.LLVMIntPredicate.LLVMIntEQ, lhs_value.value, rhs_value.value, ""); - - if (name != null) { - const ptr = self.environment.get_variable(name.?) orelse unreachable; - - _ = core.LLVMBuildStore(self.builder, cmp, ptr.value); - ptr.type = core.LLVMInt1Type(); + const op = switch (exp.typ) { + .EQ => types.LLVMIntPredicate.LLVMIntEQ, + .LT => types.LLVMIntPredicate.LLVMIntSLT, + .GT => types.LLVMIntPredicate.LLVMIntSGT, + }; + const cmp = core.LLVMBuildICmp(self.builder, op, lhs_value.value, rhs_value.value, ""); - return ptr; - } else { - return try self.create_variable(.{ - .value = cmp, - .type = core.LLVMInt1Type(), - .stack_level = null, - }); - } + return self.generate_literal(cmp, core.LLVMInt1Type(), name); }, else => unreachable, }; } fn generate_literal(self: *CodeGen, literal_val: types.LLVMValueRef, literal_type: types.LLVMTypeRef, name: ?[]const u8) !*Variable { - var variable: types.LLVMValueRef = undefined; if (name != null) { if (self.environment.scope_stack.items.len == 1) { const ptr = try self.create_variable(.{ @@ -495,12 +439,10 @@ pub const CodeGen = struct { _ = core.LLVMBuildStore(self.builder, literal_val, ptr.value) orelse return CodeGenError.CompilationError; ptr.type = literal_type; return ptr; - } else { - variable = literal_val; } return try self.create_variable(.{ - .value = variable, + .value = literal_val, .type = literal_type, .stack_level = null, }); diff --git a/src/parser.zig b/src/parser.zig index f7a6806..ad2b8d0 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -30,10 +30,7 @@ pub const Node = union(enum) { condition: *Node, statements: []*Node, }, - EQUALITY_EXPRESSION: struct { - lhs: *Node, - rhs: *Node, - }, + EQUALITY_EXPRESSION: struct { lhs: *Node, rhs: *Node, typ: EqualityExpressionType }, ADDITIVE_EXPRESSION: struct { addition: bool, lhs: *Node, @@ -79,6 +76,12 @@ pub const Node = union(enum) { }, }; +pub const EqualityExpressionType = enum { + EQ, + LT, + GT, +}; + pub const Parser = struct { tokens: []tokenizer.Token, offset: u32, @@ -266,20 +269,38 @@ pub const Parser = struct { return ParserError.ParsingError; } - // EqualityExpression ::= AdditiveExpression "==" AdditiveExpression + // EqualityExpression ::= AdditiveExpression ("==" | "<" | ">") AdditiveExpression fn parse_equality_expression(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing equality expression {any}\n", .{self.peek_token()}); const lhs = try self.parse_additive_expression(); - _ = try self.parse_token(tokenizer.TokenType.EQUALS); - _ = try self.parse_token(tokenizer.TokenType.EQUALS); + var typ: EqualityExpressionType = undefined; + + if (self.accept_parse(struct { + fn parse(iself: *Parser) ParserError!*Node { + _ = try iself.parse_token(tokenizer.TokenType.EQUALS); + _ = try iself.parse_token(tokenizer.TokenType.EQUALS); + return try iself.create_node(.{ .PROGRAM = .{ + .statements = &[_]*Node{}, + } }); + } + }.parse) != null) { + typ = .EQ; + } else if (self.accept_token(tokenizer.TokenType.LESS) != null) { + typ = .LT; + } else if (self.accept_token(tokenizer.TokenType.GREATER) != null) { + typ = .GT; + } else { + return ParserError.ParsingError; + } const rhs = try self.parse_additive_expression(); return self.create_node(.{ .EQUALITY_EXPRESSION = .{ .lhs = lhs, .rhs = rhs, + .typ = typ, } }); } diff --git a/src/tokenizer.zig b/src/tokenizer.zig index 908c016..99ed10d 100644 --- a/src/tokenizer.zig +++ b/src/tokenizer.zig @@ -26,6 +26,8 @@ pub const TokenType = union(enum) { MUL: void, DIV: void, BANG: void, + LESS: void, + GREATER: void, // Punctuation SEMICOLON: void, @@ -84,6 +86,8 @@ pub const Tokenizer = struct { 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(.{ .BANG = void{} }); + if (self.accept_string("<")) return self.create_token(.{ .LESS = void{} }); + if (self.accept_string(">")) return self.create_token(.{ .GREATER = void{} }); const string = self.consume_string(); if (string.len == 0) return TokenizerError.TokenizingError; |