Commit ed2a19dcec
Changed files (3)
src-self-hosted
test
src-self-hosted/c_tokenizer.zig
@@ -25,6 +25,7 @@ pub const CToken = struct {
Tilde,
Shl,
Lt,
+ Comma,
};
pub const NumLitSuffix = enum {
@@ -191,6 +192,10 @@ fn next(chars: [*]const u8, i: *usize) !CToken {
result.id = .Tilde;
return result;
},
+ ',' => {
+ result.id = .Comma;
+ return result;
+ },
else => return error.TokenizingFailed,
}
},
src-self-hosted/translate_c.zig
@@ -2039,7 +2039,7 @@ fn transCreateNodeUnwrapNull(c: *Context, wrapped: *ast.Node) !*ast.Node {
_ = try appendToken(c, .Period, ".");
const qm = try appendToken(c, .QuestionMark, "?");
const node = try c.a().create(ast.Node.SuffixOp);
- node.* = ast.Node.SuffixOp{
+ node.* = .{
.op = .UnwrapOptional,
.lhs = .{ .node = wrapped },
.rtoken = qm,
@@ -2047,6 +2047,39 @@ fn transCreateNodeUnwrapNull(c: *Context, wrapped: *ast.Node) !*ast.Node {
return &node.base;
}
+fn transCreateNodeEnumLiteral(c: *Context, name: []const u8) !*ast.Node {
+ const node = try c.a().create(ast.Node.EnumLiteral);
+ node.* = .{
+ .dot = try appendToken(c, .Period, "."),
+ .name = try appendIdentifier(c, name),
+ };
+ return &node.base;
+}
+
+fn transCreateNodeIf(c: *Context) !*ast.Node.If {
+ const if_tok = try appendToken(c, .Keyword_if, "if");
+ _ = try appendToken(c, .LParen, "(");
+ const node = try c.a().create(ast.Node.If);
+ node.* = .{
+ .if_token = if_tok,
+ .condition = undefined,
+ .payload = null,
+ .body = undefined,
+ .@"else" = null,
+ };
+ return node;
+}
+
+fn transCreateNodeElse(c: *Context) !*ast.Node.Else {
+ const node = try c.a().create(ast.Node.Else);
+ node.* = .{
+ .else_token = try appendToken(c, .Keyword_else, "else"),
+ .payload = null,
+ .body = undefined,
+ };
+ return node;
+}
+
const RestorePoint = struct {
c: *Context,
token_index: ast.TokenIndex,
@@ -2722,26 +2755,102 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc:
};
return &node.base;
},
- .Minus => {
- const node = try transCreateNodePrefixOp(
- rp.c,
- .Negation,
- .Minus,
- "-",
- );
- node.rhs = try parseCNumLit(rp, it.next().?, source_loc);
- return &node.base;
- },
.NumLitInt, .NumLitFloat => {
return parseCNumLit(rp, tok, source_loc);
},
.Identifier => return transCreateNodeIdentifier(rp.c, tok.bytes),
.LParen => {
- _ = try appendToken(rp.c, .LParen, "(");
const inner_node = try parseCExpr(rp, it, source_loc);
- _ = try appendToken(rp.c, .RParen, ")");
- return inner_node; // TODO
+ // hack to get zig fmt to render a comma in builtin calls
+ _ = try appendToken(rp.c, .Comma, ",");
+
+ if (it.peek().?.id == .RParen) {
+ _ = it.next();
+ return inner_node;
+ }
+
+ const node_to_cast = try parseCExpr(rp, it, source_loc);
+
+ if (it.next().?.id != .RParen) {
+ return revertAndWarn(
+ rp,
+ error.ParseError,
+ source_loc,
+ "unable to translate C expr",
+ .{},
+ );
+ }
+
+ //if (@typeId(@TypeOf(x)) == .Pointer)
+ // @ptrCast(dest, x)
+ //else if (@typeId(@TypeOf(x)) == .Integer)
+ // @intToPtr(dest, x)
+ //else
+ // @as(dest, x)
+
+ const if_1 = try transCreateNodeIf(rp.c);
+ const type_id_1 = try transCreateNodeBuiltinFnCall(rp.c, "@typeId");
+ const type_of_1 = try transCreateNodeBuiltinFnCall(rp.c, "@TypeOf");
+ try type_id_1.params.push(&type_of_1.base);
+ try type_of_1.params.push(node_to_cast);
+ type_of_1.rparen_token = try appendToken(rp.c, .LParen, ")");
+ type_id_1.rparen_token = try appendToken(rp.c, .LParen, ")");
+
+ const cmp_1 = try rp.c.a().create(ast.Node.InfixOp);
+ cmp_1.* = .{
+ .op_token = try appendToken(rp.c, .EqualEqual, "=="),
+ .lhs = &type_id_1.base,
+ .op = .EqualEqual,
+ .rhs = try transCreateNodeEnumLiteral(rp.c, "Pointer"),
+ };
+ if_1.condition = &cmp_1.base;
+ _ = try appendToken(rp.c, .LParen, ")");
+
+ const ptr_cast = try transCreateNodeBuiltinFnCall(rp.c, "@ptrCast");
+ try ptr_cast.params.push(inner_node);
+ try ptr_cast.params.push(node_to_cast);
+ ptr_cast.rparen_token = try appendToken(rp.c, .LParen, ")");
+ if_1.body = &ptr_cast.base;
+
+ const else_1 = try transCreateNodeElse(rp.c);
+ if_1.@"else" = else_1;
+
+ const if_2 = try transCreateNodeIf(rp.c);
+ const type_id_2 = try transCreateNodeBuiltinFnCall(rp.c, "@typeId");
+ const type_of_2 = try transCreateNodeBuiltinFnCall(rp.c, "@TypeOf");
+ try type_id_2.params.push(&type_of_2.base);
+ try type_of_2.params.push(node_to_cast);
+ type_of_2.rparen_token = try appendToken(rp.c, .LParen, ")");
+ type_id_2.rparen_token = try appendToken(rp.c, .LParen, ")");
+
+ const cmp_2 = try rp.c.a().create(ast.Node.InfixOp);
+ cmp_2.* = .{
+ .op_token = try appendToken(rp.c, .EqualEqual, "=="),
+ .lhs = &type_id_2.base,
+ .op = .EqualEqual,
+ .rhs = try transCreateNodeEnumLiteral(rp.c, "Int"),
+ };
+ if_2.condition = &cmp_2.base;
+ else_1.body = &if_2.base;
+ _ = try appendToken(rp.c, .LParen, ")");
+
+ const int_to_ptr = try transCreateNodeBuiltinFnCall(rp.c, "@intToPtr");
+ try int_to_ptr.params.push(inner_node);
+ try int_to_ptr.params.push(node_to_cast);
+ int_to_ptr.rparen_token = try appendToken(rp.c, .LParen, ")");
+ if_2.body = &int_to_ptr.base;
+
+ const else_2 = try transCreateNodeElse(rp.c);
+ if_2.@"else" = else_2;
+
+ const as = try transCreateNodeBuiltinFnCall(rp.c, "@as");
+ try as.params.push(inner_node);
+ try as.params.push(node_to_cast);
+ as.rparen_token = try appendToken(rp.c, .LParen, ")");
+ else_2.body = &as.base;
+
+ return &if_1.base;
},
else => return revertAndWarn(
rp,
@@ -2780,6 +2889,30 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
};
node = &access_node.base;
},
+ .Asterisk => {
+ if (it.peek().?.id == .RParen) {
+ // type *)
+
+ // hack to get zig fmt to render a comma in builtin calls
+ _ = try appendToken(rp.c, .Comma, ",");
+
+ const ptr = try transCreateNodePtrType(rp.c, false, false, .Identifier);
+ ptr.rhs = node;
+ return &ptr.base;
+ } else {
+ // expr * expr
+ const op_token = try appendToken(rp.c, .Asterisk, "*");
+ const rhs = try parseCPrimaryExpr(rp, it, source_loc);
+ const bitshift_node = try rp.c.a().create(ast.Node.InfixOp);
+ bitshift_node.* = .{
+ .op_token = op_token,
+ .lhs = node,
+ .op = .BitShiftLeft,
+ .rhs = rhs,
+ };
+ node = &bitshift_node.base;
+ }
+ },
.Shl => {
const op_token = try appendToken(rp.c, .AngleBracketAngleBracketLeft, "<<");
const rhs = try parseCPrimaryExpr(rp, it, source_loc);
@@ -2819,6 +2952,16 @@ fn parseCPrefixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
node.rhs = try parseCPrefixOpExpr(rp, it, source_loc);
return &node.base;
},
+ .Asterisk => {
+ const prefix_op_expr = try parseCPrefixOpExpr(rp, it, source_loc);
+ const node = try rp.c.a().create(ast.Node.SuffixOp);
+ node.* = .{
+ .lhs = .{ .node = prefix_op_expr },
+ .op = .Deref,
+ .rtoken = try appendToken(rp.c, .PeriodAsterisk, ".*"),
+ };
+ return &node.base;
+ },
else => {
_ = it.prev();
return try parseCSuffixOpExpr(rp, it, source_loc);
@@ -2833,7 +2976,7 @@ fn tokenSlice(c: *Context, token: ast.TokenIndex) []const u8 {
fn getFnDecl(c: *Context, ref: *ast.Node) ?*ast.Node {
const init = ref.cast(ast.Node.VarDecl).?.init_node.?;
- const name = if (init.cast(ast.Node.Identifier)) |id|
+ const name = if (init.cast(ast.Node.Identifier)) |id|
tokenSlice(c, id.token)
else
return null;
test/translate_c.zig
@@ -397,6 +397,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub const OpenGLProcs = union_OpenGLProcs;
});
+ cases.add_2("macro pointer cast",
+ \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
+ , &[_][]const u8{
+ \\pub const NRF_GPIO = if (@typeId(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@TypeOf(NRF_GPIO_BASE)) == .Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE);
+ });
+
/////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
cases.add_both("typedef of function in struct field",