diff options
| author | Veikka Tuominen <git@vexu.eu> | 2021-01-31 12:55:33 +0200 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2021-02-16 16:37:07 +0200 |
| commit | d835f5cce5fc3b296f55e208905d9ff4d368e497 (patch) | |
| tree | defa873d5bc10497d98599534068b409cdaa782d /src | |
| parent | 6ecec4c8b761c9f8f272602ccb2abdfd9656c71c (diff) | |
| download | zig-d835f5cce5fc3b296f55e208905d9ff4d368e497.tar.gz zig-d835f5cce5fc3b296f55e208905d9ff4d368e497.zip | |
translate-c: make Node more like Type
Diffstat (limited to 'src')
| -rw-r--r-- | src/translate_c/ast.zig | 224 | ||||
| -rw-r--r-- | src/type.zig | 5 |
2 files changed, 147 insertions, 82 deletions
diff --git a/src/translate_c/ast.zig b/src/translate_c/ast.zig index 4418971269..0585c26d18 100644 --- a/src/translate_c/ast.zig +++ b/src/translate_c/ast.zig @@ -2,14 +2,19 @@ const std = @import("std"); const Type = @import("../type.zig").Type; pub const Node = struct { - tag: Tag, - // type: Type = Type.initTag(.noreturn), + /// If the tag value is less than Tag.no_payload_count, then no pointer + /// dereference is needed. + tag_if_small_enough: usize, + ptr_otherwise: *Payload, pub const Tag = enum { null_literal, undefined_literal, opaque_literal, - bool_literal, + true_literal, + false_literal, + // After this, the tag requires a payload. + int, float, string, @@ -39,12 +44,18 @@ pub const Node = struct { discard, block, + pub const last_no_payload_tag = Tag.false_literal; + pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; + pub fn Type(tag: Tag) ?type { return switch (tag) { - .null_literal => null, - .undefined_literal => null, - .opaque_literal => null, - .bool_literal, + .null_literal, + .undefined_literal, + .opaque_literal, + .true_literal, + .false_litral, + => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"), + .int, .float, .string, @@ -54,144 +65,186 @@ pub const Node = struct { .field_access_arrow, .warning, .failed_decl, - => Value, - .@"if" => If, - .@"while" => While, - .@"switch" => Switch, - .@"break" => Break, - .call => Call, + => Payload.Value, + .@"if" => Payload.If, + .@"while" => Payload.While, + .@"switch" => Payload.Switch, + .@"break" => Payload.Break, + .call => Payload.Call, .array_access, .std_mem_zeroes, .@"return", .discard, - => SingleArg, - .var_decl => VarDecl, - .func => Func, - .@"enum" => Enum, - .@"struct", .@"union" => Record, - .array_init => ArrayInit, - .container_init => ContainerInit, - .std_meta_cast => Infix, - .block => Block, + => Payload.SingleArg, + .var_decl => Payload.VarDecl, + .func => Payload.Func, + .@"enum" => Payload.Enum, + .@"struct", .@"union" => Payload.Record, + .array_init => Payload.ArrayInit, + .container_init => Payload.ContainerInit, + .std_meta_cast => Payload.Infix, + .block => Payload.Block, + }; + } + + pub fn init(comptime t: Tag) Node { + comptime std.debug.assert(@enumToInt(t) < Tag.no_payload_count); + return .{ .tag_if_small_enough = @enumToInt(t) }; + } + + pub fn create(comptime t: Tag, ally: *Allocator, data: Data(t)) error{OutOfMemory}!Node { + const ptr = try ally.create(t.Type()); + ptr.* = .{ + .base = .{ .tag = t }, + .data = data, }; + return Node{ .ptr_otherwise = &ptr.base }; + } + + pub fn Data(comptime t: Tag) type { + return std.meta.fieldInfo(t.Type(), .data).field_type; } }; +}; + +pub const Payload = struct { + tag: Tag, pub const Infix = struct { base: Node, - lhs: *Node, - rhs: *Node, + data: struct { + lhs: *Node, + rhs: *Node, + }, }; pub const Value = struct { base: Node, - val: []const u8, + data: []const u8, }; pub const SingleArg = struct { base: Node, - index: *Node, + data: *Node, }; pub const If = struct { base: Node = .{ .tag = .@"if" }, - cond: *Node, - then: *Node, - @"else": ?*Node, + data: struct { + cond: *Node, + then: *Node, + @"else": ?*Node, + }, }; pub const While = struct { base: Node = .{ .tag = .@"while" }, - cond: *Node, - body: *Node, + data: struct { + cond: *Node, + body: *Node, + }, }; pub const Switch = struct { base: Node = .{ .tag = .@"switch" }, - cond: *Node, - cases: []Prong, - default: ?[]const u8, + data: struct { + cond: *Node, + cases: []Prong, + default: ?[]const u8, - pub const Prong = struct { - lhs: *Node, - rhs: ?*Node, - label: []const u8, - }; + pub const Prong = struct { + lhs: *Node, + rhs: ?*Node, + label: []const u8, + }; + }, }; pub const Break = struct { base: Node = .{ .tag = .@"break" }, - label: ?[]const u8, - rhs: ?*Node, + data: struct { + label: ?[]const u8, + rhs: ?*Node, + }, }; pub const Call = struct { base: Node = .{.call}, - lhs: *Node, - args: []*Node, + data: struct { + lhs: *Node, + args: []*Node, + }, }; pub const VarDecl = struct { base: Node = .{ .tag = .var_decl }, - @"pub": bool, - @"const": bool, - @"extern": bool, - @"export": bool, - name: []const u8, - type: Type, - init: *Node, + data: struct { + @"pub": bool, + @"const": bool, + @"extern": bool, + @"export": bool, + name: []const u8, + type: Type, + init: *Node, + }, }; pub const Func = struct { base: Node = .{.func}, - @"pub": bool, - @"extern": bool, - @"export": bool, - name: []const u8, - cc: std.builtin.CallingConvention, - params: []Param, - return_type: Type, - body: ?*Node, - - pub const Param = struct { - @"noalias": bool, - name: ?[]const u8, - type: Type, - }; + data: struct { + @"pub": bool, + @"extern": bool, + @"export": bool, + name: []const u8, + cc: std.builtin.CallingConvention, + params: []Param, + return_type: Type, + body: ?*Node, + + pub const Param = struct { + @"noalias": bool, + name: ?[]const u8, + type: Type, + }; + }, }; pub const Enum = struct { base: Node = .{ .tag = .@"enum" }, - name: ?[]const u8, - fields: []Field, + data: struct { + name: ?[]const u8, + fields: []Field, - pub const Field = struct { - name: []const u8, - value: ?[]const u8, - }; + pub const Field = struct { + name: []const u8, + value: ?[]const u8, + }; + }, }; pub const Record = struct { base: Node, - name: ?[]const u8, - @"packed": bool, - fields: []Field, + data: struct { + name: ?[]const u8, + @"packed": bool, + fields: []Field, - pub const Field = struct { - name: []const u8, - type: Type, - alignment: c_uint, - }; + pub const Field = struct { + name: []const u8, + type: Type, + alignment: c_uint, + }; + }, }; pub const ArrayInit = struct { base: Node = .{ .tag = .array_init }, - values: []*Node, + data: []*Node, }; pub const ContainerInit = struct { base: Node = .{ .tag = .container_init }, - values: []Initializer, + data: []Initializer, pub const Initializer = struct { name: []const u8, @@ -201,7 +254,14 @@ pub const Node = struct { pub const Block = struct { base: Node = .{ .tag = .block }, - label: ?[]const u8, - stmts: []*Node, + data: struct { + label: ?[]const u8, + stmts: []*Node, + }, }; }; + +/// Converts the nodes into a Zig ast and then renders it. +pub fn render(allocator: *Allocator, nodes: []const Node) !void { + @panic("TODO"); +} diff --git a/src/type.zig b/src/type.zig index 7d3308e403..8fcaba6fad 100644 --- a/src/type.zig +++ b/src/type.zig @@ -3408,6 +3408,11 @@ pub const Type = extern union { }; } + pub fn init(comptime t: Tag) Type { + comptime std.debug.assert(@enumToInt(t) < Tag.no_payload_count); + return .{ .tag_if_small_enough = @enumToInt(t) }; + } + pub fn create(comptime t: Tag, ally: *Allocator, data: Data(t)) error{OutOfMemory}!Type { const ptr = try ally.create(t.Type()); ptr.* = .{ |
