aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2021-02-13 17:57:52 +0200
committerVeikka Tuominen <git@vexu.eu>2021-02-16 16:40:39 +0200
commitd7460db044ef6649486a27f2b9ebb1de9e2ce2b0 (patch)
tree8961f52cb5ea3e4a6e423c1738a9e898808838c4 /src
parent13a9db208566449cd6bcfa5fd77f2707f7c9f394 (diff)
downloadzig-d7460db044ef6649486a27f2b9ebb1de9e2ce2b0.tar.gz
zig-d7460db044ef6649486a27f2b9ebb1de9e2ce2b0.zip
translate-c: render a bunch of simple nodes and calls
Diffstat (limited to 'src')
-rw-r--r--src/translate_c.zig5
-rw-r--r--src/translate_c/ast.zig297
2 files changed, 267 insertions, 35 deletions
diff --git a/src/translate_c.zig b/src/translate_c.zig
index c7a30ff919..9b80582ab5 100644
--- a/src/translate_c.zig
+++ b/src/translate_c.zig
@@ -3054,6 +3054,7 @@ fn maybeSuppressResult(
fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void {
_ = try c.global_scope.sym_table.put(name, decl_node);
+ try c.global_scope.nodes.append(decl_node);
}
/// Translate a qual type for a variable with an initializer. The initializer
@@ -3903,10 +3904,10 @@ fn fail(
pub fn failDecl(c: *Context, loc: clang.SourceLocation, name: []const u8, comptime format: []const u8, args: anytype) Error!void {
// location
// pub const name = @compileError(msg);
+ const fail_msg = try std.fmt.allocPrint(c.arena, format, args);
+ try c.global_scope.nodes.append(try Tag.fail_decl.create(c.arena, .{ .actual = name, .mangled = fail_msg }));
const location_comment = try std.fmt.allocPrint(c.arena, "// {s}", .{c.locStr(loc)});
try c.global_scope.nodes.append(try Tag.warning.create(c.arena, location_comment));
- const fail_msg = try std.fmt.allocPrint(c.arena, format, args);
- try c.global_scope.nodes.append(try Tag.fail_decl.create(c.arena, fail_msg));
}
pub fn freeErrors(errors: []ClangErrMsg) void {
diff --git a/src/translate_c/ast.zig b/src/translate_c/ast.zig
index 8e18b55c04..4e91f13757 100644
--- a/src/translate_c/ast.zig
+++ b/src/translate_c/ast.zig
@@ -52,7 +52,6 @@ pub const Node = extern union {
var_decl,
func,
warning,
- failed_decl,
/// All enums are non-exhaustive
@"enum",
@"struct",
@@ -339,9 +338,7 @@ pub const Node = extern union {
.char_literal,
.identifier,
.warning,
- .failed_decl,
.type,
- .fail_decl,
=> Payload.Value,
.@"if" => Payload.If,
.@"while" => Payload.While,
@@ -359,7 +356,7 @@ pub const Node = extern union {
.block => Payload.Block,
.c_pointer, .single_pointer => Payload.Pointer,
.array_type => Payload.Array,
- .arg_redecl, .alias => Payload.ArgRedecl,
+ .arg_redecl, .alias, .fail_decl => Payload.ArgRedecl,
.log2_int_type => Payload.Log2IntType,
.typedef, .pub_typedef, .var_simple, .pub_var_simple => Payload.SimpleVarDecl,
.enum_redecl => Payload.EnumRedecl,
@@ -695,7 +692,7 @@ const Context = struct {
extra_data: std.ArrayListUnmanaged(std.zig.ast.Node.Index) = .{},
tokens: std.zig.ast.TokenList = .{},
- fn appendTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex {
+ fn addTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex {
const start_index = c.buf.items.len;
try c.buf.writer().print(format ++ " ", args);
@@ -707,13 +704,13 @@ const Context = struct {
return @intCast(u32, c.tokens.len - 1);
}
- fn appendToken(c: *Context, tag: TokenTag, bytes: []const u8) Allocator.Error!TokenIndex {
- std.debug.assert(tag != .identifier); // use appendIdentifier
- return appendTokenFmt(c, tag, "{s}", .{bytes});
+ fn addToken(c: *Context, tag: TokenTag, bytes: []const u8) Allocator.Error!TokenIndex {
+ std.debug.assert(tag != .identifier); // use addIdentifier
+ return addTokenFmt(c, tag, "{s}", .{bytes});
}
- fn appendIdentifier(c: *Context, bytes: []const u8) Allocator.Error!TokenIndex {
- return appendTokenFmt(c, .identifier, "{s}", .{std.zig.fmtId(bytes)});
+ fn addIdentifier(c: *Context, bytes: []const u8) Allocator.Error!TokenIndex {
+ return addTokenFmt(c, .identifier, "{s}", .{std.zig.fmtId(bytes)});
}
fn listToSpan(c: *Context, list: []const NodeIndex) Allocator.Error!NodeSubRange {
@@ -724,14 +721,14 @@ const Context = struct {
};
}
- fn appendNode(c: *Context, elem: std.zig.ast.NodeList.Elem) Allocator.Error!NodeIndex {
+ fn addNode(c: *Context, elem: std.zig.ast.NodeList.Elem) Allocator.Error!NodeIndex {
const result = @intCast(NodeIndex, c.nodes.len);
try c.nodes.append(c.gpa, elem);
return result;
}
};
-fn renderNodes(c: *Context, nodes: []const Node) !NodeSubRange {
+fn renderNodes(c: *Context, nodes: []const Node) Allocator.Error!NodeSubRange {
var result = std.ArrayList(NodeIndex).init(c.gpa);
defer result.deinit();
@@ -744,7 +741,7 @@ fn renderNodes(c: *Context, nodes: []const Node) !NodeSubRange {
return try c.listToSpan(result.items);
}
-fn renderNode(c: *Context, node: Node) !NodeIndex {
+fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
switch (node.tag()) {
.warning => {
const payload = node.castTag(.warning).?;
@@ -754,12 +751,12 @@ fn renderNode(c: *Context, node: Node) !NodeIndex {
},
.usingnamespace_builtins => {
// pub usingnamespace @import("std").c.builtins;
- _ = try c.appendToken(.keyword_pub, "pub");
- const usingnamespace_token = try c.appendToken(.keyword_usingnamespace, "usingnamespace");
+ _ = try c.addToken(.keyword_pub, "pub");
+ const usingnamespace_token = try c.addToken(.keyword_usingnamespace, "usingnamespace");
const import_node = try renderStdImport(c, "c", "builtins");
- _ = try c.appendToken(.semicolon, ";");
+ _ = try c.addToken(.semicolon, ";");
- return c.appendNode(.{
+ return c.addNode(.{
.tag = .@"usingnamespace",
.main_token = usingnamespace_token,
.data = .{
@@ -768,6 +765,196 @@ fn renderNode(c: *Context, node: Node) !NodeIndex {
},
});
},
+ .std_math_Log2Int => {
+ const payload = node.castTag(.std_math_Log2Int).?;
+ const import_node = try renderStdImport(c, "math", "Log2Int");
+ return renderCall(c, import_node, &.{payload.data});
+ },
+ .std_meta_cast => {
+ const payload = node.castTag(.std_meta_cast).?;
+ const import_node = try renderStdImport(c, "meta", "cast");
+ return renderCall(c, import_node, &.{ payload.data.lhs, payload.data.rhs });
+ },
+ .std_meta_sizeof => {
+ const payload = node.castTag(.std_meta_sizeof).?;
+ const import_node = try renderStdImport(c, "meta", "sizeof");
+ return renderCall(c, import_node, &.{payload.data});
+ },
+ .std_mem_zeroes => {
+ const payload = node.castTag(.std_mem_zeroes).?;
+ const import_node = try renderStdImport(c, "mem", "zeroes");
+ return renderCall(c, import_node, &.{payload.data});
+ },
+ .std_mem_zeroinit => {
+ const payload = node.castTag(.std_mem_zeroinit).?;
+ const import_node = try renderStdImport(c, "mem", "zeroInit");
+ return renderCall(c, import_node, &.{ payload.data.lhs, payload.data.rhs });
+ },
+ .call => {
+ const payload = node.castTag(.call).?;
+ const lhs = try renderNode(c, payload.data.lhs);
+ return renderCall(c, lhs, payload.data.args);
+ },
+ .null_literal => return c.addNode(.{
+ .tag = .null_literal,
+ .main_token = try c.addToken(.keyword_null, "null"),
+ .data = .{
+ .lhs = undefined,
+ .rhs = undefined,
+ },
+ }),
+ .undefined_literal => return c.addNode(.{
+ .tag = .undefined_literal,
+ .main_token = try c.addToken(.keyword_undefined, "undefined"),
+ .data = .{
+ .lhs = undefined,
+ .rhs = undefined,
+ },
+ }),
+ .true_literal => return c.addNode(.{
+ .tag = .true_literal,
+ .main_token = try c.addToken(.keyword_true, "true"),
+ .data = .{
+ .lhs = undefined,
+ .rhs = undefined,
+ },
+ }),
+ .false_literal => return c.addNode(.{
+ .tag = .false_literal,
+ .main_token = try c.addToken(.keyword_false, "false"),
+ .data = .{
+ .lhs = undefined,
+ .rhs = undefined,
+ },
+ }),
+ .zero_literal => return c.addNode(.{
+ .tag = .integer_literal,
+ .main_token = try c.addToken(.integer_literal, "0"),
+ .data = .{
+ .lhs = undefined,
+ .rhs = undefined,
+ },
+ }),
+ .one_literal => return c.addNode(.{
+ .tag = .integer_literal,
+ .main_token = try c.addToken(.integer_literal, "1"),
+ .data = .{
+ .lhs = undefined,
+ .rhs = undefined,
+ },
+ }),
+ .void_type => return c.addNode(.{
+ .tag = .identifier,
+ .main_token = try c.addToken(.identifier, "void"),
+ .data = .{
+ .lhs = undefined,
+ .rhs = undefined,
+ },
+ }),
+ .@"anytype" => return try c.addNode(.{
+ .tag = .@"anytype",
+ .main_token = try c.addToken(.keyword_anytype, "anytype"),
+ .data = .{
+ .lhs = undefined,
+ .rhs = undefined,
+ },
+ }),
+ .type => {
+ const payload = node.castTag(.type).?;
+ return c.addNode(.{
+ .tag = .identifier,
+ .main_token = try c.addToken(.identifier, payload.data),
+ .data = .{
+ .lhs = undefined,
+ .rhs = undefined,
+ },
+ });
+ },
+ .identifier => {
+ const payload = node.castTag(.identifier).?;
+ return c.addNode(.{
+ .tag = .identifier,
+ .main_token = try c.addIdentifier(payload.data),
+ .data = .{
+ .lhs = undefined,
+ .rhs = undefined,
+ },
+ });
+ },
+ .number_literal => {
+ const payload = node.castTag(.number_literal).?;
+ return c.addNode(.{
+ .tag = .identifier,
+ // might be integer or float, but it doesn't matter for rendering
+ .main_token = try c.addToken(.integer_literal, payload.data),
+ .data = .{
+ .lhs = undefined,
+ .rhs = undefined,
+ },
+ });
+ },
+ .string_literal => {
+ const payload = node.castTag(.string_literal).?;
+ return c.addNode(.{
+ .tag = .identifier,
+ .main_token = try c.addToken(.char_literal, payload.data),
+ .data = .{
+ .lhs = undefined,
+ .rhs = undefined,
+ },
+ });
+ },
+ .char_literal => {
+ const payload = node.castTag(.char_literal).?;
+ return c.addNode(.{
+ .tag = .identifier,
+ .main_token = try c.addToken(.string_literal, payload.data),
+ .data = .{
+ .lhs = undefined,
+ .rhs = undefined,
+ },
+ });
+ },
+ .fail_decl => {
+ const payload = node.castTag(.fail_decl).?;
+ // pub const name = @compileError(msg);
+ _ = try c.addToken(.keyword_pub, "pub");
+ const const_kw = try c.addToken(.keyword_const, "const");
+ _ = try c.addIdentifier(payload.data.actual);
+ _ = try c.addToken(.equal, "=");
+
+
+ const compile_error_tok = try c.addToken(.builtin, "@compileError");
+ _ = try c.addToken(.l_paren, "(");
+ const err_msg_tok = try c.addTokenFmt(.string_literal, "\"{s}\"", .{std.zig.fmtEscapes(payload.data.mangled)});
+ const err_msg = try c.addNode(.{
+ .tag = .string_literal,
+ .main_token = err_msg_tok,
+ .data = .{
+ .lhs = undefined,
+ .rhs = undefined,
+ },
+ });
+ _ = try c.addToken(.r_paren, ")");
+ const compile_error = try c.addNode(.{
+ .tag = .builtin_call_two,
+ .main_token = compile_error_tok,
+ .data = .{
+ .lhs = err_msg,
+ .rhs = 0,
+ },
+ });
+ _ = try c.addToken(.semicolon, ";");
+
+ return c.addNode(.{
+ .tag = .simple_var_decl,
+ .main_token = const_kw,
+ .data = .{
+ .lhs = 0,
+ .rhs = compile_error,
+ }
+ });
+ },
else => {
try c.buf.writer().print("// TODO renderNode {}\n", .{node.tag()});
return @as(u32, 0); // error: integer value 0 cannot be coerced to type 'std.mem.Allocator.Error!u32'
@@ -776,22 +963,20 @@ fn renderNode(c: *Context, node: Node) !NodeIndex {
}
fn renderStdImport(c: *Context, first: []const u8, second: []const u8) !NodeIndex {
- const import_tok = try c.appendToken(.builtin, "@import");
- _ = try c.appendToken(.l_paren, "(");
-
- const std_tok = try c.appendToken(.string_literal, "\"std\"");
- const std_node = try c.appendNode(.{
+ const import_tok = try c.addToken(.builtin, "@import");
+ _ = try c.addToken(.l_paren, "(");
+ const std_tok = try c.addToken(.string_literal, "\"std\"");
+ const std_node = try c.addNode(.{
.tag = .string_literal,
.main_token = std_tok,
.data = .{
- .lhs = std_tok,
- .rhs = std_tok,
+ .lhs = undefined,
+ .rhs = undefined,
},
});
+ _ = try c.addToken(.r_paren, ")");
- _ = try c.appendToken(.r_paren, ")");
-
- const import_node = try c.appendNode(.{
+ const import_node = try c.addNode(.{
.tag = .builtin_call_two,
.main_token = import_tok,
.data = .{
@@ -801,21 +986,67 @@ fn renderStdImport(c: *Context, first: []const u8, second: []const u8) !NodeInde
});
var access_chain = import_node;
- access_chain = try c.appendNode(.{
+ access_chain = try c.addNode(.{
.tag = .field_access,
- .main_token = try c.appendToken(.period, "."),
+ .main_token = try c.addToken(.period, "."),
.data = .{
.lhs = access_chain,
- .rhs = try c.appendIdentifier(first),
+ .rhs = try c.addIdentifier(first),
},
});
- access_chain = try c.appendNode(.{
+ access_chain = try c.addNode(.{
.tag = .field_access,
- .main_token = try c.appendToken(.period, "."),
+ .main_token = try c.addToken(.period, "."),
.data = .{
.lhs = access_chain,
- .rhs = try c.appendIdentifier(second),
+ .rhs = try c.addIdentifier(second),
},
});
return access_chain;
}
+
+fn renderCall(c: *Context, lhs: NodeIndex, args: []const Node) !NodeIndex {
+ const lparen = try c.addToken(.l_paren, "(");
+ const res = switch (args.len) {
+ 0 => try c.addNode(.{
+ .tag = .call_one,
+ .main_token = lparen,
+ .data = .{
+ .lhs = lhs,
+ .rhs = 0,
+ },
+ }),
+ 1 => blk: {
+ const arg = try renderNode(c, args[0]);
+ break :blk try c.addNode(.{
+ .tag = .call_one,
+ .main_token = lparen,
+ .data = .{
+ .lhs = lhs,
+ .rhs = arg,
+ },
+ });
+ },
+ else => blk: {
+ const start = @intCast(u32, c.extra_data.items.len);
+ const end = @intCast(u32, start + args.len);
+ try c.extra_data.ensureCapacity(c.gpa, end + 2); // + 2 for span start + end
+ for (args) |arg, i| {
+ if (i != 0) _ = try c.addToken(.comma, ",");
+ c.extra_data.appendAssumeCapacity(try renderNode(c, arg));
+ }
+ c.extra_data.appendAssumeCapacity(start);
+ c.extra_data.appendAssumeCapacity(end);
+ break :blk try c.addNode(.{
+ .tag = .call_comma,
+ .main_token = lparen,
+ .data = .{
+ .lhs = lhs,
+ .rhs = end + 2,
+ },
+ });
+ },
+ };
+ _ = try c.addToken(.r_paren, ")");
+ return res;
+}