authorchloe caruso <git@paperclover.net> 2024-10-29 00:07:51-07:00
committerchloe caruso <git@paperclover.net> 2024-10-29 00:07:51-07:00
logb1f64e4c22560b8bf8cfa321d28ea21308dfb957
tree0c4f0fa4b44c7552543f9046fc5385d1e577048c
parent2bcfa5e47db1ba080d7add7d2cd7a59e0e249bd1
signature Commit is signed but in an unrecognized format.

feat: parse enums


5 files changed, 137 insertions(+), 3 deletions(-)

CHANGELOG.md+2
...@@ -1,5 +1,7 @@...@@ -1,5 +1,7 @@
1## 0.1.81## 0.1.8
22
3- feat: implement basic enum types
4
3## 0.1.75## 0.1.7
46
5- news: rename the language to "ix"7- news: rename the language to "ix"
src/core/Ast.Dump.zig+15
...@@ -177,6 +177,21 @@ fn dumpNode(writer: anytype, state: *State, node: NodeIndex) @TypeOf(writer).Err...@@ -177,6 +177,21 @@ fn dumpNode(writer: anytype, state: *State, node: NodeIndex) @TypeOf(writer).Err
177 try dumpNode(writer, state, ty);177 try dumpNode(writer, state, ty);
178 }178 }
179 },179 },
180 .enum_field => {
181 try writer.writeAll(" ");
182 const enum_field = state.ast.fullEnumField(node);
183 try tty.setColor(writer, .magenta);
184 try writer.writeAll(enum_field.id);
185 try tty.setColor(writer, .reset);
186 if (enum_field.payload) |ty| {
187 try writer.writeAll(": ");
188 try dumpNode(writer, state, ty);
189 }
190 if (enum_field.value) |ty| {
191 try writer.writeAll(" = ");
192 try dumpNode(writer, state, ty);
193 }
194 },
180 .bin => {195 .bin => {
181 try writer.writeAll(" (");196 try writer.writeAll(" (");
182 {197 {
src/core/Ast.zig+35
...@@ -215,6 +215,12 @@ pub const Node = struct {...@@ -215,6 +215,12 @@ pub const Node = struct {
215 struct_field,215 struct_field,
216 /// Struct Init216 /// Struct Init
217 struct_init,217 struct_init,
218 /// Enum Declaration
219 @"enum",
220 /// Enum Field
221 enum_field,
222 /// Enum Literal
223 enum_literal,
218 /// Array type224 /// Array type
219 array_type,225 array_type,
220 /// Array initialization226 /// Array initialization
...@@ -336,6 +342,9 @@ pub const Node = struct {...@@ -336,6 +342,9 @@ pub const Node = struct {
336 .shl_assign = .bin,342 .shl_assign = .bin,
337 .shr = .bin,343 .shr = .bin,
338 .shr_assign = .bin,344 .shr_assign = .bin,
345 .@"enum" = .list,
346 .enum_literal = .none,
347 .enum_field = .none,
339 .string = .none,348 .string = .none,
340 .struct_decl = .list,349 .struct_decl = .list,
341 .array_type = .un,350 .array_type = .un,
...@@ -371,6 +380,10 @@ pub const Node = struct {...@@ -371,6 +380,10 @@ pub const Node = struct {
371 type: OptionalNodeIndex,380 type: OptionalNodeIndex,
372 unused: Unused = .zero,381 unused: Unused = .zero,
373 },382 },
383 enum_field: struct {
384 payload: OptionalNodeIndex,
385 value: OptionalNodeIndex,
386 },
374 bin: struct {387 bin: struct {
375 lhs: NodeIndex,388 lhs: NodeIndex,
376 rhs: NodeIndex,389 rhs: NodeIndex,
...@@ -566,6 +579,13 @@ pub const full = struct {...@@ -566,6 +579,13 @@ pub const full = struct {
566 id: []const u8,579 id: []const u8,
567 type: ?NodeIndex,580 type: ?NodeIndex,
568 };581 };
582
583 pub const EnumField = struct {
584 start_token: TokenIndex,
585 id: []const u8,
586 payload: ?NodeIndex,
587 value: ?NodeIndex,
588 };
569};589};
570590
571pub fn deinit(ast: *Ast, gpa: std.mem.Allocator) void {591pub fn deinit(ast: *Ast, gpa: std.mem.Allocator) void {
...@@ -691,6 +711,21 @@ pub fn fullParamDecl(ast: Ast, node: NodeIndex) full.ParamDecl {...@@ -691,6 +711,21 @@ pub fn fullParamDecl(ast: Ast, node: NodeIndex) full.ParamDecl {
691 };711 };
692}712}
693713
714pub fn fullEnumField(ast: Ast, node: NodeIndex) full.EnumField {
715 const tok_tags = ast.tokens.items(.tag);
716
717 const main_token = ast.nodes.items(.main_token)[node];
718 assert(tok_tags[main_token] == .id);
719 const id = ast.tokenSlice(main_token);
720 const data = ast.nodes.items(.data)[node].enum_field;
721 return .{
722 .start_token = main_token,
723 .id = id,
724 .payload = data.payload.unwrap(),
725 .value = data.value.unwrap(),
726 };
727}
728
694pub fn fullStructField(ast: Ast, node: NodeIndex) full.StructField {729pub fn fullStructField(ast: Ast, node: NodeIndex) full.StructField {
695 const tok_tags = ast.tokens.items(.tag);730 const tok_tags = ast.tokens.items(.tag);
696731
src/core/Parse.zig+80-3
...@@ -86,9 +86,10 @@ pub const ExpectedContext = enum {...@@ -86,9 +86,10 @@ pub const ExpectedContext = enum {
86 statement,86 statement,
87 expression,87 expression,
88 else_clause,88 else_clause,
89 enum_field,
89 struct_field,90 struct_field,
90 param_list,
91 static_field,91 static_field,
92 param_list,
9293
93 pub fn description(tag: ExpectedContext) []const u8 {94 pub fn description(tag: ExpectedContext) []const u8 {
94 return switch (tag) {95 return switch (tag) {
...@@ -99,6 +100,7 @@ pub const ExpectedContext = enum {...@@ -99,6 +100,7 @@ pub const ExpectedContext = enum {
99 .expression => "an expression",100 .expression => "an expression",
100 .else_clause => "an else clause",101 .else_clause => "an else clause",
101 .struct_field => "a field definition",102 .struct_field => "a field definition",
103 .enum_field => "an enum field",
102 .static_field => "a field name or number",104 .static_field => "a field name or number",
103 };105 };
104 }106 }
...@@ -415,7 +417,8 @@ fn parseModuleMembers(p: *Parse) Error!SubList {...@@ -415,7 +417,8 @@ fn parseModuleMembers(p: *Parse) Error!SubList {
415 => try p.scratch.append(p.gpa, try p.parseModuleDecl()),417 => try p.scratch.append(p.gpa, try p.parseModuleDecl()),
416418
417 .kw_struct => try p.scratch.append(p.gpa, try p.parseStructDecl(.declaration)),419 .kw_struct => try p.scratch.append(p.gpa, try p.parseStructDecl(.declaration)),
418 .kw_tuple => try p.scratch.append(p.gpa, try p.parseStructDecl(.declaration)),420 .kw_tuple => try p.scratch.append(p.gpa, try p.parseTupleDecl(.declaration)),
421 .kw_enum => try p.scratch.append(p.gpa, try p.parseEnumDecl(.declaration)),
419422
420 .id => if (p.isContextualKeyword("test")) {423 .id => if (p.isContextualKeyword("test")) {
421 try p.scratch.append(p.gpa, try p.parseTestDecl());424 try p.scratch.append(p.gpa, try p.parseTestDecl());
...@@ -423,7 +426,6 @@ fn parseModuleMembers(p: *Parse) Error!SubList {...@@ -423,7 +426,6 @@ fn parseModuleMembers(p: *Parse) Error!SubList {
423 try p.parseExpressionStatement();426 try p.parseExpressionStatement();
424 },427 },
425428
426 .kw_enum,
427 .kw_trait,429 .kw_trait,
428 .kw_impl,430 .kw_impl,
429 => |tag| std.debug.panic("TODO: parse {s}", .{@tagName(tag)}),431 => |tag| std.debug.panic("TODO: parse {s}", .{@tagName(tag)}),
...@@ -608,6 +610,28 @@ fn parseTupleDecl(p: *Parse, ctx: ExprParseContext) Error!NodeIndex {...@@ -608,6 +610,28 @@ fn parseTupleDecl(p: *Parse, ctx: ExprParseContext) Error!NodeIndex {
608 });610 });
609}611}
610612
613fn parseEnumDecl(p: *Parse, ctx: ExprParseContext) Error!NodeIndex {
614 const trace = t.trace(@src());
615 defer trace.end();
616
617 const main_token = p.assertToken(.kw_enum);
618
619 switch (ctx) {
620 .declaration => _ = try p.expect(.id),
621 else => {},
622 }
623
624 _ = try p.expect(.start_brace);
625
626 const fields = try p.parseEnumFieldList();
627
628 return try p.addNode(.{
629 .tag = .@"enum",
630 .main_token = main_token,
631 .data = .{ .list = fields },
632 });
633}
634
611fn parseTestDecl(p: *Parse) Error!NodeIndex {635fn parseTestDecl(p: *Parse) Error!NodeIndex {
612 const trace = t.trace(@src());636 const trace = t.trace(@src());
613 defer trace.end();637 defer trace.end();
...@@ -657,6 +681,33 @@ fn parseStructFieldList(p: *Parse) Error!SubList {...@@ -657,6 +681,33 @@ fn parseStructFieldList(p: *Parse) Error!SubList {
657 return p.scratchToSubList(scratch_top);681 return p.scratchToSubList(scratch_top);
658}682}
659683
684fn parseEnumFieldList(p: *Parse) Error!SubList {
685 const trace = t.trace(@src());
686 defer trace.end();
687
688 const scratch_top = p.scratch.items.len;
689 defer p.scratch.shrinkRetainingCapacity(scratch_top);
690
691 while (true) {
692 const trace_param = t.traceFmt(@src(), "Param {d}", .{p.scratch.items.len - scratch_top});
693 defer trace_param.end();
694
695 if (p.currentTag() == .end_brace) break;
696
697 try p.scratch.append(p.gpa, try p.parseEnumField());
698
699 switch (p.currentTag()) {
700 .comma => _ = p.nextToken(),
701 .end_brace => break,
702 else => return p.failUnexpectedToken(.enum_field),
703 }
704 }
705
706 _ = p.assertToken(.end_brace);
707
708 return p.scratchToSubList(scratch_top);
709}
710
660fn parseStructField(p: *Parse) Error!NodeIndex {711fn parseStructField(p: *Parse) Error!NodeIndex {
661 const trace = t.trace(@src());712 const trace = t.trace(@src());
662 defer trace.end();713 defer trace.end();
...@@ -674,6 +725,32 @@ fn parseStructField(p: *Parse) Error!NodeIndex {...@@ -674,6 +725,32 @@ fn parseStructField(p: *Parse) Error!NodeIndex {
674 });725 });
675}726}
676727
728fn parseEnumField(p: *Parse) Error!NodeIndex {
729 const trace = t.trace(@src());
730 defer trace.end();
731
732 const main_token = try p.expect(.id);
733
734 const payload = if (p.eatToken(.colon)) |_|
735 try p.parseExpressionOrFail(.expression)
736 else
737 null;
738
739 const value = if (p.eatToken(.equal)) |_|
740 try p.parseExpressionOrFail(.expression)
741 else
742 null;
743
744 return try p.addNode(.{
745 .tag = .struct_field,
746 .main_token = main_token,
747 .data = .{ .enum_field = .{
748 .payload = .init(payload),
749 .value = .init(value),
750 } },
751 });
752}
753
677fn parseBlock(p: *Parse) Error!NodeIndex {754fn parseBlock(p: *Parse) Error!NodeIndex {
678 const trace = t.trace(@src());755 const trace = t.trace(@src());
679 defer trace.end();756 defer trace.end();
test/behavior/enum.ix created+5
...@@ -0,0 +1,5 @@
1enum Mode {
2 first,
3 second,
4 @"enum",
5}