From 5409e79d4e2917e8daa4d7d218b0cf25686ffe98 Mon Sep 17 00:00:00 2001 From: Baitinq Date: Fri, 6 Jun 2025 00:21:08 +0200 Subject: Feature: Support declaring type aliases --- grammar.ebnf | 4 +++- src/bootstrap/tokenizer.src | 8 ++++++++ src/codegen.zig | 9 +++++++++ src/parser.zig | 21 ++++++++++++++++++++- src/tokenizer.zig | 2 ++ 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/grammar.ebnf b/grammar.ebnf index cecc65e..48667b2 100644 --- a/grammar.ebnf +++ b/grammar.ebnf @@ -34,7 +34,7 @@ UnaryExpression ::= ("!" | "-" | "*") UnaryExpression | PostfixExpression PostfixExpression ::= PrimaryExpression (FieldAccess | FunctionCallStatement | CastStatement | SizeOfStatement)* -PrimaryExpression ::= NULL | NUMBER | BOOLEAN | CHAR | STRING | IDENTIFIER | FunctionDefinition | StructDefinition | StructInstantiation | FieldAccess | LPAREN Expression RPAREN +PrimaryExpression ::= NULL | NUMBER | BOOLEAN | CHAR | STRING | IDENTIFIER | FunctionDefinition | TypeDefinition | StructDefinition | StructInstantiation | FieldAccess | LPAREN Expression RPAREN FunctionDefinition ::= LPAREN FunctionParameters? RPAREN ARROW IDENTIFIER LBRACE Statement* ReturnStatement SEMICOLON RBRACE @@ -46,6 +46,8 @@ FunctionType ::= LPAREN (Type ("," Type)*)? RPAREN ARROW Type ParameterTypes ::= Type ("," Type)* +TypeDefinition ::= "newtype" Type + StructDefinition ::= "struct" LBRACE (StructField ("," StructField)*)? RBRACE StructField ::= IDENTIFIER ":" Type diff --git a/src/bootstrap/tokenizer.src b/src/bootstrap/tokenizer.src index 3716e79..814a377 100644 --- a/src/bootstrap/tokenizer.src +++ b/src/bootstrap/tokenizer.src @@ -17,6 +17,7 @@ let TOKEN_BREAK = 7; let TOKEN_CONTINUE = 8; let TOKEN_ARROW = 9; let TOKEN_STRUCT = 10; +let TOKEN_TYPE = 34; /* Identifiers */ let TOKEN_IDENTIFIER = 11; @@ -97,6 +98,9 @@ let print_tokens = (ts: *token, ts_len: i64) => i64 { if (to.type == TOKEN_STRUCT) { printf("Struct\n"); }; + if (to.type == TOKEN_TYPE) { + printf("Type\n"); + }; if (to.type == TOKEN_IDENTIFIER) { printf("Identifier: %s\n", cast(*i8, to.data)); }; @@ -390,6 +394,10 @@ let tokenizer_next = (t: *tokenizer) => *token { (*to).type = TOKEN_STRUCT; return to; }; + if tokenizer_accept_string(t, "newtype") { + (*to).type = TOKEN_TYPE; + return to; + }; if tokenizer_accept_string(t, "=>") { (*to).type = TOKEN_ARROW; diff --git a/src/codegen.zig b/src/codegen.zig index 118e274..8f2b9fa 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -765,6 +765,15 @@ pub const CodeGen = struct { .node_type = simple_type_node, }); }, + .SIMPLE_TYPE => |t| { + return try self.create_variable(.{ + .value = null, + .type = try self.get_llvm_type(t.underlying_type.?), + .stack_level = null, + .node = expression, + .node_type = t.underlying_type.?, + }); + }, else => unreachable, } }, diff --git a/src/parser.zig b/src/parser.zig index e92ed51..da3c71c 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -589,11 +589,12 @@ pub const Parser = struct { } } - // PrimaryExpression ::= NULL | NUMBER | BOOLEAN | CHAR | STRING | IDENTIFIER | FunctionDefinition | StructDefinition | StructInstantiation | FieldAccess | LPAREN Expression RPAREN + // PrimaryExpression ::= NULL | NUMBER | BOOLEAN | CHAR | STRING | IDENTIFIER | FunctionDefinition | TypeDefinition | StructDefinition | StructInstantiation | FieldAccess | LPAREN Expression RPAREN fn parse_primary_expression(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing primary expression {any}\n", .{self.peek_token()}); if (self.accept_parse(parse_function_definition)) |stmt| return stmt; + if (self.accept_parse(parse_type_definition)) |stmt| return stmt; if (self.accept_parse(parse_struct_definition)) |stmt| return stmt; if (self.accept_parse(parse_struct_instanciation)) |stmt| return stmt; @@ -706,6 +707,24 @@ pub const Parser = struct { return node_list.items; } + // TypeDefinition ::= "newtype" Type + fn parse_type_definition(self: *Parser) ParserError!*Node { + errdefer if (!self.try_context) std.debug.print("Error parsing type definition {any}\n", .{self.peek_token()}); + + _ = try self.parse_token(tokenizer.TokenType.TYPE); + + const typ = try self.parse_type(); + + return self.create_node(.{ + .TYPE = .{ + .SIMPLE_TYPE = .{ + .name = "", + .underlying_type = typ, + }, + }, + }); + } + // StructDefinition ::= "struct" LBRACE StructFields? RBRACE fn parse_struct_definition(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing struct definition {any}\n", .{self.peek_token()}); diff --git a/src/tokenizer.zig b/src/tokenizer.zig index f6fbf11..5dacc75 100644 --- a/src/tokenizer.zig +++ b/src/tokenizer.zig @@ -16,6 +16,7 @@ pub const TokenType = union(enum) { CONTINUE: void, ARROW: void, STRUCT: void, + TYPE: void, // Identifiers IDENTIFIER: []u8, @@ -101,6 +102,7 @@ pub const Tokenizer = struct { if (self.accept_string("false")) return self.create_token(.{ .BOOLEAN = false }); if (self.accept_string("null")) return self.create_token(.{ .NULL = void{} }); if (self.accept_string("struct")) return self.create_token(.{ .STRUCT = void{} }); + if (self.accept_string("newtype")) return self.create_token(.{ .TYPE = void{} }); if (self.accept_string("=>")) return self.create_token(.{ .ARROW = void{} }); if (self.accept_string(";")) return self.create_token(.{ .SEMICOLON = void{} }); -- cgit 1.4.1