authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-08 11:52:21+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-16 16:40:05+02:00
log5dac3683c9e8819d6ceefb869577e3537d863c41
tree491c201e264afb8c8301fd48863ed76333c449f1
parentbb867b071a9e2fa69f39a45532dffa0f51ffdbfd
signature Commit is signed but in an unrecognized format.

translate-c: convert record and enum decls


2 files changed, 125 insertions(+), 229 deletions(-)

src/translate_c.zig+90-206
......@@ -783,7 +783,7 @@ fn transCreateNodeTypedef(
783783
784784 const payload = try c.arena.create(ast.Payload.Typedef);
785785 payload.* = .{
786 .base = .{ .tag = ([2]ast.Node.Tag{ .typedef, .pub_typedef })[toplevel] },
786 .base = .{ .tag = ([2]ast.Node.Tag{ .typedef, .pub_typedef })[@boolToInt(toplevel)] },
787787 .data = .{
788788 .name = checked_name,
789789 .init = init_node,
......@@ -792,7 +792,7 @@ fn transCreateNodeTypedef(
792792 return Node.initPayload(&payload.base);
793793}
794794
795fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?*ast.Node {
795fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Node {
796796 if (c.decl_table.get(@ptrToInt(record_decl.getCanonicalDecl()))) |name|
797797 return try transCreateNodeIdentifier(c, name); // Avoid processing this decl twice
798798 const record_loc = record_decl.getLocation();
......@@ -807,46 +807,30 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?*as
807807 }
808808
809809 var container_kind_name: []const u8 = undefined;
810 var container_kind: std.zig.Token.Id = undefined;
810 var is_union = false;
811811 if (record_decl.isUnion()) {
812812 container_kind_name = "union";
813 container_kind = .Keyword_union;
813 is_union = true;
814814 } else if (record_decl.isStruct()) {
815815 container_kind_name = "struct";
816 container_kind = .Keyword_struct;
817816 } else {
818 try emitWarning(c, record_loc, "record {s} is not a struct or union", .{bare_name});
817 try warn(c, record_loc, "record {s} is not a struct or union", .{bare_name});
819818 return null;
820819 }
821820
822821 const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ container_kind_name, bare_name });
823822 _ = try c.decl_table.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), name);
824823
825 const visib_tok = if (!is_unnamed) try appendToken(c, .Keyword_pub, "pub") else null;
826 const mut_tok = try appendToken(c, .Keyword_const, "const");
827 const name_tok = try appendIdentifier(c, name);
828
829 const eq_token = try appendToken(c, .Equal, "=");
830
831 var semicolon: ast.TokenIndex = undefined;
824 const is_pub = !is_unnamed;
832825 const init_node = blk: {
833 const rp = makeRestorePoint(c);
834826 const record_def = record_decl.getDefinition() orelse {
835827 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
836 const opaque_type = try transCreateNodeOpaqueType(c);
837 semicolon = try appendToken(c, .Semicolon, ";");
838 break :blk opaque_type;
828 break :blk Node.opaque_literal.init();
839829 };
840830
841 const layout_tok = try if (record_decl.getPackedAttribute())
842 appendToken(c, .Keyword_packed, "packed")
843 else
844 appendToken(c, .Keyword_extern, "extern");
845 const container_tok = try appendToken(c, container_kind, container_kind_name);
846 const lbrace_token = try appendToken(c, .LBrace, "{");
847
848 var fields_and_decls = std.ArrayList(*ast.Node).init(c.gpa);
849 defer fields_and_decls.deinit();
831 const is_packed = record_decl.getPackedAttribute();
832 var fields = std.ArrayList(ast.Payload.Record.Field).init(c.gpa);
833 defer fields.deinit();
850834
851835 var unnamed_field_count: u32 = 0;
852836 var it = record_def.field_begin();
......@@ -858,110 +842,82 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?*as
858842
859843 if (field_decl.isBitField()) {
860844 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
861 const opaque_type = try transCreateNodeOpaqueType(c);
862 semicolon = try appendToken(c, .Semicolon, ";");
863 try emitWarning(c, field_loc, "{s} demoted to opaque type - has bitfield", .{container_kind_name});
864 break :blk opaque_type;
845 try warn(c, field_loc, "{s} demoted to opaque type - has bitfield", .{container_kind_name});
846 break :blk Node.opaque_literal.init();
865847 }
866848
867849 if (qualTypeCanon(field_qt).isIncompleteOrZeroLengthArrayType(c.clang_context)) {
868850 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
869 const opaque_type = try transCreateNodeOpaqueType(c);
870 semicolon = try appendToken(c, .Semicolon, ";");
871 try emitWarning(c, field_loc, "{s} demoted to opaque type - has variable length array", .{container_kind_name});
872 break :blk opaque_type;
851 try warn(c, field_loc, "{s} demoted to opaque type - has variable length array", .{container_kind_name});
852 break :blk Node.opaque_literal.init();
873853 }
874854
875855 var is_anon = false;
876 var raw_name = try c.str(@ptrCast(*const clang.NamedDecl, field_decl).getName_bytes_begin());
877 if (field_decl.isAnonymousStructOrUnion() or raw_name.len == 0) {
856 var field_name = try c.str(@ptrCast(*const clang.NamedDecl, field_decl).getName_bytes_begin());
857 if (field_decl.isAnonymousStructOrUnion() or field_name.len == 0) {
878858 // Context.getMangle() is not used here because doing so causes unpredictable field names for anonymous fields.
879 raw_name = try std.fmt.allocPrint(c.arena, "unnamed_{d}", .{unnamed_field_count});
859 field_name = try std.fmt.allocPrint(c.arena, "unnamed_{d}", .{unnamed_field_count});
880860 unnamed_field_count += 1;
881861 is_anon = true;
882862 }
883 const field_name = try appendIdentifier(c, raw_name);
884 _ = try appendToken(c, .Colon, ":");
885 const field_type = transQualType(rp, field_qt, field_loc) catch |err| switch (err) {
863 const field_type = transQualType(c, field_qt, field_loc) catch |err| switch (err) {
886864 error.UnsupportedType => {
887865 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
888 const opaque_type = try transCreateNodeOpaqueType(c);
889 semicolon = try appendToken(c, .Semicolon, ";");
890 try emitWarning(c, record_loc, "{s} demoted to opaque type - unable to translate type of field {s}", .{ container_kind_name, raw_name });
891 break :blk opaque_type;
866 try warn(c, record_loc, "{s} demoted to opaque type - unable to translate type of field {s}", .{ container_kind_name, raw_name });
867 break :blk Node.opaque_literal.init();
892868 },
893869 else => |e| return e,
894870 };
895871
896 const align_expr = blk_2: {
872 const alignment = blk_2: {
897873 const alignment = field_decl.getAlignedAttribute(c.clang_context);
898874 if (alignment != 0) {
899 _ = try appendToken(c, .Keyword_align, "align");
900 _ = try appendToken(c, .LParen, "(");
901875 // Clang reports the alignment in bits
902 const expr = try transCreateNodeInt(c, alignment / 8);
903 _ = try appendToken(c, .RParen, ")");
904
905 break :blk_2 expr;
876 break :blk_2 alignment / 8;
906877 }
907878 break :blk_2 null;
908879 };
909880
910 const field_node = try c.arena.create(ast.Node.ContainerField);
911 field_node.* = .{
912 .doc_comments = null,
913 .comptime_token = null,
914 .name_token = field_name,
915 .type_expr = field_type,
916 .value_expr = null,
917 .align_expr = align_expr,
918 };
919
920881 if (is_anon) {
921 _ = try c.decl_table.put(
922 c.gpa,
923 @ptrToInt(field_decl.getCanonicalDecl()),
924 raw_name,
925 );
882 _ = try c.decl_table.put(c.gpa, @ptrToInt(field_decl.getCanonicalDecl()), field_name);
926883 }
927884
928 try fields_and_decls.append(&field_node.base);
929 _ = try appendToken(c, .Comma, ",");
885 try fields.append(.{
886 .name = field_name,
887 .type = field_type,
888 .alignment = alignment,
889 });
930890 }
931 const container_node = try ast.Node.ContainerDecl.alloc(c.arena, fields_and_decls.items.len);
891
892 const payload = try c.arena.create(ast.Payload.Record);
932893 container_node.* = .{
933 .layout_token = layout_tok,
934 .kind_token = container_tok,
935 .init_arg_expr = .None,
936 .fields_and_decls_len = fields_and_decls.items.len,
937 .lbrace_token = lbrace_token,
938 .rbrace_token = try appendToken(c, .RBrace, "}"),
894 .base = .{ .tag = ([2]ast.Node.Tag{ .@"struct", .@"union" })[@boolToInt(is_union)] },
895 .data = .{
896 .is_packed = is_packed,
897 .fields = try c.arena.dupe(ast.Payload.Record.Field, fields.items),
898 },
939899 };
940 mem.copy(*ast.Node, container_node.fieldsAndDecls(), fields_and_decls.items);
941 semicolon = try appendToken(c, .Semicolon, ";");
942 break :blk &container_node.base;
900 break :blk Node.initPayload(&container_node.base);
943901 };
944902
945 const node = try ast.Node.VarDecl.create(c.arena, .{
946 .name_token = name_tok,
947 .mut_token = mut_tok,
948 .semicolon_token = semicolon,
949 }, .{
950 .visib_token = visib_tok,
951 .eq_token = eq_token,
952 .init_node = init_node,
953 });
903 const payload = try c.arena.create(ast.Payload.SimpleVarDecl);
904 payload.* = .{
905 .base = .{ .tag = ([2]ast.Node.Tag{ .var_simple, .pub_var_simple })[@boolToInt(is_pub)] },
906 .data = .{
907 .name = name,
908 .init = init_node,
909 },
910 };
954911
955 try addTopLevelDecl(c, name, &node.base);
912 try addTopLevelDecl(c, name, Node.initPayload(&payload.base));
956913 if (!is_unnamed)
957914 try c.alias_list.append(.{ .alias = bare_name, .name = name });
958 return transCreateNodeIdentifier(c, name);
915 return Node.identifier.create(c.arena, name);
959916}
960917
961fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?*ast.Node {
918fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
962919 if (c.decl_table.get(@ptrToInt(enum_decl.getCanonicalDecl()))) |name|
963920 return try transCreateNodeIdentifier(c, name); // Avoid processing this decl twice
964 const rp = makeRestorePoint(c);
965921 const enum_loc = enum_decl.getLocation();
966922
967923 var bare_name = try c.str(@ptrCast(*const clang.NamedDecl, enum_decl).getName_bytes_begin());
......@@ -974,10 +930,7 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?*ast.Node
974930 const name = try std.fmt.allocPrint(c.arena, "enum_{s}", .{bare_name});
975931 _ = try c.decl_table.put(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), name);
976932
977 const visib_tok = if (!is_unnamed) try appendToken(c, .Keyword_pub, "pub") else null;
978 const mut_tok = try appendToken(c, .Keyword_const, "const");
979 const name_tok = try appendIdentifier(c, name);
980 const eq_token = try appendToken(c, .Equal, "=");
933 const is_pub = !is_unnamed;
981934
982935 const init_node = if (enum_decl.getDefinition()) |enum_def| blk: {
983936 var pure_enum = true;
......@@ -991,11 +944,8 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?*ast.Node
991944 }
992945 }
993946
994 const extern_tok = try appendToken(c, .Keyword_extern, "extern");
995 const container_tok = try appendToken(c, .Keyword_enum, "enum");
996
997 var fields_and_decls = std.ArrayList(*ast.Node).init(c.gpa);
998 defer fields_and_decls.deinit();
947 var fields = std.ArrayList(ast.Payload.Enum.Field).init(c.gpa);
948 defer fields.deinit();
999949
1000950 const int_type = enum_decl.getIntegerType();
1001951 // The underlying type may be null in case of forward-declared enum
......@@ -1003,30 +953,23 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?*ast.Node
1003953 // default to the usual integer type used for all the enums.
1004954
1005955 // default to c_int since msvc and gcc default to different types
1006 _ = try appendToken(c, .LParen, "(");
1007 const init_arg_expr = ast.Node.ContainerDecl.InitArg{
1008 .Type = if (int_type.ptr != null and
1009 !isCBuiltinType(int_type, .UInt) and
1010 !isCBuiltinType(int_type, .Int))
1011 transQualType(rp, int_type, enum_loc) catch |err| switch (err) {
1012 error.UnsupportedType => {
1013 try failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
1014 return null;
1015 },
1016 else => |e| return e,
1017 }
1018 else
1019 try transCreateNodeIdentifier(c, "c_int"),
1020 };
1021 _ = try appendToken(c, .RParen, ")");
1022
1023 const lbrace_token = try appendToken(c, .LBrace, "{");
956 const init_arg_expr = if (int_type.ptr != null and
957 !isCBuiltinType(int_type, .UInt) and
958 !isCBuiltinType(int_type, .Int))
959 transQualType(c, int_type, enum_loc) catch |err| switch (err) {
960 error.UnsupportedType => {
961 try failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
962 return null;
963 },
964 else => |e| return e,
965 }
966 else
967 try Node.type.create(c.arena, "c_int");
1024968
1025969 it = enum_def.enumerator_begin();
1026970 end_it = enum_def.enumerator_end();
1027971 while (it.neq(end_it)) : (it = it.next()) {
1028972 const enum_const = it.deref();
1029
1030973 const enum_val_name = try c.str(@ptrCast(*const clang.NamedDecl, enum_const).getName_bytes_begin());
1031974
1032975 const field_name = if (!is_unnamed and mem.startsWith(u8, enum_val_name, bare_name))
......@@ -1034,100 +977,41 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?*ast.Node
1034977 else
1035978 enum_val_name;
1036979
1037 const field_name_tok = try appendIdentifier(c, field_name);
1038
1039 const int_node = if (!pure_enum) blk_2: {
1040 _ = try appendToken(c, .Colon, "=");
1041 break :blk_2 try transCreateNodeAPInt(c, enum_const.getInitVal());
1042 } else
980 const int_node = if (!pure_enum)
981 try transCreateNodeAPInt(c, enum_const.getInitVal())
982 else
1043983 null;
1044984
1045 const field_node = try c.arena.create(ast.Node.ContainerField);
1046 field_node.* = .{
1047 .doc_comments = null,
1048 .comptime_token = null,
1049 .name_token = field_name_tok,
1050 .type_expr = null,
1051 .value_expr = int_node,
1052 .align_expr = null,
1053 };
1054
1055 try fields_and_decls.append(&field_node.base);
1056 _ = try appendToken(c, .Comma, ",");
985 try fields_and_decls.append(.{
986 .name = field_name,
987 .value = int_node,
988 });
1057989
1058990 // In C each enum value is in the global namespace. So we put them there too.
1059991 // At this point we can rely on the enum emitting successfully.
1060 const tld_visib_tok = try appendToken(c, .Keyword_pub, "pub");
1061 const tld_mut_tok = try appendToken(c, .Keyword_const, "const");
1062 const tld_name_tok = try appendIdentifier(c, enum_val_name);
1063 const tld_eq_token = try appendToken(c, .Equal, "=");
1064 const cast_node = try rp.c.createBuiltinCall("@enumToInt", 1);
1065 const enum_ident = try transCreateNodeIdentifier(c, name);
1066 const period_tok = try appendToken(c, .Period, ".");
1067 const field_ident = try transCreateNodeIdentifier(c, field_name);
1068 const field_access_node = try c.arena.create(ast.Node.SimpleInfixOp);
1069 field_access_node.* = .{
1070 .base = .{ .tag = .Period },
1071 .op_token = period_tok,
1072 .lhs = enum_ident,
1073 .rhs = field_ident,
1074 };
1075 cast_node.params()[0] = &field_access_node.base;
1076 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1077 const tld_init_node = &cast_node.base;
1078 const tld_semicolon_token = try appendToken(c, .Semicolon, ";");
1079 const tld_node = try ast.Node.VarDecl.create(c.arena, .{
1080 .name_token = tld_name_tok,
1081 .mut_token = tld_mut_tok,
1082 .semicolon_token = tld_semicolon_token,
1083 }, .{
1084 .visib_token = tld_visib_tok,
1085 .eq_token = tld_eq_token,
1086 .init_node = tld_init_node,
1087 });
1088 try addTopLevelDecl(c, field_name, &tld_node.base);
992 try addTopLevelDecl(c, field_name, try Node.enum_redecl.create(c.arena, .{
993 .enum_val_name = enum_val_name,
994 .field_name = field_name,
995 .enum_name = name,
996 }));
1089997 }
1090 // make non exhaustive
1091 const field_node = try c.arena.create(ast.Node.ContainerField);
1092 field_node.* = .{
1093 .doc_comments = null,
1094 .comptime_token = null,
1095 .name_token = try appendIdentifier(c, "_"),
1096 .type_expr = null,
1097 .value_expr = null,
1098 .align_expr = null,
1099 };
1100998
1101 try fields_and_decls.append(&field_node.base);
1102 _ = try appendToken(c, .Comma, ",");
1103 const container_node = try ast.Node.ContainerDecl.alloc(c.arena, fields_and_decls.items.len);
1104 container_node.* = .{
1105 .layout_token = extern_tok,
1106 .kind_token = container_tok,
1107 .init_arg_expr = init_arg_expr,
1108 .fields_and_decls_len = fields_and_decls.items.len,
1109 .lbrace_token = lbrace_token,
1110 .rbrace_token = try appendToken(c, .RBrace, "}"),
1111 };
1112 mem.copy(*ast.Node, container_node.fieldsAndDecls(), fields_and_decls.items);
1113 break :blk &container_node.base;
999 break :blk try Node.@"enum".create(c.arena, try c.arena.dupe(ast.Payload.Enum.Field, fields.items));
11141000 } else blk: {
11151001 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), {});
1116 break :blk try transCreateNodeOpaqueType(c);
1002 break :blk Node.opaque_literal.init();
11171003 };
11181004
1119 const semicolon_token = try appendToken(c, .Semicolon, ";");
1120 const node = try ast.Node.VarDecl.create(c.arena, .{
1121 .name_token = name_tok,
1122 .mut_token = mut_tok,
1123 .semicolon_token = semicolon_token,
1124 }, .{
1125 .visib_token = visib_tok,
1126 .eq_token = eq_token,
1127 .init_node = init_node,
1128 });
1005 const payload = try c.arena.create(ast.Payload.SimpleVarDecl);
1006 payload.* = .{
1007 .base = .{ .tag = ([2]ast.Node.Tag{ .var_simple, .pub_var_simple })[@boolToInt(is_pub)] },
1008 .data = .{
1009 .name = name,
1010 .init = init_node,
1011 },
1012 };
11291013
1130 try addTopLevelDecl(c, name, &node.base);
1014 try addTopLevelDecl(c, name, Node.initPayload(&payload.base));
11311015 if (!is_unnamed)
11321016 try c.alias_list.append(.{ .alias = bare_name, .name = name });
11331017 return transCreateNodeIdentifier(c, name);
......@@ -1382,22 +1266,22 @@ fn transCompoundStmt(c: *Context, scope: *Scope, stmt: *const clang.CompoundStmt
13821266}
13831267
13841268fn transCStyleCastExprClass(
1385 rp: RestorePoint,
1269 c: *Context,
13861270 scope: *Scope,
13871271 stmt: *const clang.CStyleCastExpr,
13881272 result_used: ResultUsed,
13891273 lrvalue: LRValue,
1390) TransError!*ast.Node {
1274) TransError!Node {
13911275 const sub_expr = stmt.getSubExpr();
13921276 const cast_node = (try transCCast(
1393 rp,
1277 c,
13941278 scope,
13951279 stmt.getBeginLoc(),
13961280 stmt.getType(),
13971281 sub_expr.getType(),
1398 try transExpr(rp, scope, sub_expr, .used, lrvalue),
1282 try transExpr(c, scope, sub_expr, .used, lrvalue),
13991283 ));
1400 return maybeSuppressResult(rp, scope, result_used, cast_node);
1284 return maybeSuppressResult(c, scope, result_used, cast_node);
14011285}
14021286
14031287fn transDeclStmtOne(
src/translate_c/ast.zig+35-23
......@@ -10,6 +10,7 @@ pub const Node = extern union {
1010 pub const Tag = enum {
1111 null_literal,
1212 undefined_literal,
13 /// opaque {}
1314 opaque_literal,
1415 true_literal,
1516 false_literal,
......@@ -42,6 +43,7 @@ pub const Node = extern union {
4243 func,
4344 warning,
4445 failed_decl,
46 /// All enums are non-exhaustive
4547 @"enum",
4648 @"struct",
4749 @"union",
......@@ -145,8 +147,12 @@ pub const Node = extern union {
145147 arg_redecl,
146148 /// const name = init;
147149 typedef,
150 var_simple,
148151 /// pub const name = init;
149152 pub_typedef,
153 pub_var_simple,
154 /// pub const enum_field_name = @enumToInt(enum_name.field_name);
155 enum_redecl,
150156
151157 pub const last_no_payload_tag = Tag.usingnamespace_builtins;
152158 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
......@@ -266,7 +272,8 @@ pub const Node = extern union {
266272 .array_type => Payload.Array,
267273 .arg_redecl => Payload.ArgRedecl,
268274 .log2_int_type => Payload.Log2IntType,
269 .typedef, .pub_typedef => Payload.Typedef,
275 .typedef, .pub_typedef, .pub_var_simple => Payload.SimpleVarDecl,
276 .enum_redecl => Payload.EnumRedecl,
270277 };
271278 }
272279
......@@ -419,41 +426,37 @@ pub const Payload = struct {
419426 return_type: Node,
420427 body: ?Node,
421428 alignment: ?c_uint,
422
423 pub const Param = struct {
424 is_noalias: bool,
425 name: ?[]const u8,
426 type: Node,
427 };
428429 },
430
431 pub const Param = struct {
432 is_noalias: bool,
433 name: ?[]const u8,
434 type: Node,
435 };
429436 };
430437
431438 pub const Enum = struct {
432439 base: Node = .{ .tag = .@"enum" },
433 data: struct {
434 name: ?[]const u8,
435 fields: []Field,
440 data: []Field,
436441
437 pub const Field = struct {
438 name: []const u8,
439 value: ?[]const u8,
440 };
441 },
442 pub const Field = struct {
443 name: []const u8,
444 value: ?Node,
445 };
442446 };
443447
444448 pub const Record = struct {
445449 base: Node,
446450 data: struct {
447 name: ?[]const u8,
448451 @"packed": bool,
449452 fields: []Field,
450
451 pub const Field = struct {
452 name: []const u8,
453 type: Type,
454 alignment: c_uint,
455 };
456453 },
454
455 pub const Field = struct {
456 name: []const u8,
457 type: Node,
458 alignment: ?c_uint,
459 };
457460 };
458461
459462 pub const ArrayInit = struct {
......@@ -514,13 +517,22 @@ pub const Payload = struct {
514517 data: std.math.Log2Int(u64),
515518 };
516519
517 pub const Typedef = struct {
520 pub const SimpleVarDecl = struct {
518521 base: Node,
519522 data: struct {
520523 name: []const u8,
521524 init: Node,
522525 },
523526 };
527
528 pub const EnumRedecl = struct {
529 base: Node,
530 data: struct {
531 enum_val_name: []const u8,
532 field_name: []const u8,
533 enum_name: []const u8,
534 },
535 };
524536};
525537
526538/// Converts the nodes into a Zig ast.