translate-c-2 member access

This commit is contained in:
Vexu 2019-12-18 22:29:42 +02:00
parent e65b9e8f7b
commit cf7a5b7a4a
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
4 changed files with 154 additions and 105 deletions

View File

@ -27,6 +27,7 @@ pub const CToken = struct {
Lt, Lt,
Comma, Comma,
Fn, Fn,
Arrow,
}; };
pub const NumLitSuffix = enum { pub const NumLitSuffix = enum {
@ -164,6 +165,8 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
NumLitIntSuffixL, NumLitIntSuffixL,
NumLitIntSuffixLL, NumLitIntSuffixLL,
NumLitIntSuffixUL, NumLitIntSuffixUL,
Minus,
Done,
} = .Start; } = .Start;
var result = CToken{ var result = CToken{
@ -178,9 +181,6 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
const c = chars[i.*]; const c = chars[i.*];
if (c == 0) { if (c == 0) {
switch (state) { switch (state) {
.Start => {
return result;
},
.Identifier, .Identifier,
.Decimal, .Decimal,
.Hex, .Hex,
@ -193,6 +193,9 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
result.bytes = chars[begin_index..i.*]; result.bytes = chars[begin_index..i.*];
return result; return result;
}, },
.Start,
.Minus,
.Done,
.NumLitIntSuffixU, .NumLitIntSuffixU,
.NumLitIntSuffixL, .NumLitIntSuffixL,
.NumLitIntSuffixUL, .NumLitIntSuffixUL,
@ -212,7 +215,6 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
=> return error.TokenizingFailed, => return error.TokenizingFailed,
} }
} }
i.* += 1;
switch (state) { switch (state) {
.Start => { .Start => {
switch (c) { switch (c) {
@ -220,12 +222,12 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
'\'' => { '\'' => {
state = .CharLit; state = .CharLit;
result.id = .CharLit; result.id = .CharLit;
begin_index = i.* - 1; begin_index = i.*;
}, },
'\"' => { '\"' => {
state = .String; state = .String;
result.id = .StrLit; result.id = .StrLit;
begin_index = i.* - 1; begin_index = i.*;
}, },
'/' => { '/' => {
state = .OpenComment; state = .OpenComment;
@ -239,21 +241,21 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
'a'...'z', 'A'...'Z', '_' => { 'a'...'z', 'A'...'Z', '_' => {
state = .Identifier; state = .Identifier;
result.id = .Identifier; result.id = .Identifier;
begin_index = i.* - 1; begin_index = i.*;
}, },
'1'...'9' => { '1'...'9' => {
state = .Decimal; state = .Decimal;
result.id = .NumLitInt; result.id = .NumLitInt;
begin_index = i.* - 1; begin_index = i.*;
}, },
'0' => { '0' => {
state = .GotZero; state = .GotZero;
result.id = .NumLitInt; result.id = .NumLitInt;
begin_index = i.* - 1; begin_index = i.*;
}, },
'.' => { '.' => {
result.id = .Dot; result.id = .Dot;
return result; state = .Done;
}, },
'<' => { '<' => {
result.id = .Lt; result.id = .Lt;
@ -261,40 +263,52 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
}, },
'(' => { '(' => {
result.id = .LParen; result.id = .LParen;
return result; state = .Done;
}, },
')' => { ')' => {
result.id = .RParen; result.id = .RParen;
return result; state = .Done;
}, },
'*' => { '*' => {
result.id = .Asterisk; result.id = .Asterisk;
return result; state = .Done;
}, },
'-' => { '-' => {
state = .Minus;
result.id = .Minus; result.id = .Minus;
return result;
}, },
'!' => { '!' => {
result.id = .Bang; result.id = .Bang;
return result; state = .Done;
}, },
'~' => { '~' => {
result.id = .Tilde; result.id = .Tilde;
return result; state = .Done;
}, },
',' => { ',' => {
result.id = .Comma; result.id = .Comma;
return result; state = .Done;
}, },
else => return error.TokenizingFailed, else => return error.TokenizingFailed,
} }
}, },
.Done => return result,
.Minus => {
switch (c) {
'>' => {
result.id = .Arrow;
state = .Done;
},
else => {
return result;
},
}
},
.GotLt => { .GotLt => {
switch (c) { switch (c) {
'<' => { '<' => {
result.id = .Shl; result.id = .Shl;
return result; state = .Done;
}, },
else => { else => {
return result; return result;
@ -310,19 +324,16 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
'f', 'f',
'F', 'F',
=> { => {
i.* -= 1;
result.num_lit_suffix = .F; result.num_lit_suffix = .F;
result.bytes = chars[begin_index..i.*]; result.bytes = chars[begin_index..i.*];
return result; state = .Done;
}, },
'l', 'L' => { 'l', 'L' => {
i.* -= 1;
result.num_lit_suffix = .L; result.num_lit_suffix = .L;
result.bytes = chars[begin_index..i.*]; result.bytes = chars[begin_index..i.*];
return result; state = .Done;
}, },
else => { else => {
i.* -= 1;
result.bytes = chars[begin_index..i.*]; result.bytes = chars[begin_index..i.*];
return result; return result;
}, },
@ -352,16 +363,15 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
'0'...'9' => {}, '0'...'9' => {},
'f', 'F' => { 'f', 'F' => {
result.num_lit_suffix = .F; result.num_lit_suffix = .F;
result.bytes = chars[begin_index .. i.* - 1]; result.bytes = chars[begin_index..i.*];
return result; state = .Done;
}, },
'l', 'L' => { 'l', 'L' => {
result.num_lit_suffix = .L; result.num_lit_suffix = .L;
result.bytes = chars[begin_index .. i.* - 1]; result.bytes = chars[begin_index..i.*];
return result; state = .Done;
}, },
else => { else => {
i.* -= 1;
result.bytes = chars[begin_index..i.*]; result.bytes = chars[begin_index..i.*];
return result; return result;
}, },
@ -374,19 +384,18 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
'u', 'U' => { 'u', 'U' => {
state = .NumLitIntSuffixU; state = .NumLitIntSuffixU;
result.num_lit_suffix = .U; result.num_lit_suffix = .U;
result.bytes = chars[begin_index .. i.* - 1]; result.bytes = chars[begin_index..i.*];
}, },
'l', 'L' => { 'l', 'L' => {
state = .NumLitIntSuffixL; state = .NumLitIntSuffixL;
result.num_lit_suffix = .L; result.num_lit_suffix = .L;
result.bytes = chars[begin_index .. i.* - 1]; result.bytes = chars[begin_index..i.*];
}, },
'.' => { '.' => {
result.id = .NumLitFloat; result.id = .NumLitFloat;
state = .Float; state = .Float;
}, },
else => { else => {
i.* -= 1;
result.bytes = chars[begin_index..i.*]; result.bytes = chars[begin_index..i.*];
return result; return result;
}, },
@ -407,12 +416,12 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
'u', 'U' => { 'u', 'U' => {
state = .NumLitIntSuffixU; state = .NumLitIntSuffixU;
result.num_lit_suffix = .U; result.num_lit_suffix = .U;
result.bytes = chars[begin_index .. i.* - 1]; result.bytes = chars[begin_index..i.*];
}, },
'l', 'L' => { 'l', 'L' => {
state = .NumLitIntSuffixL; state = .NumLitIntSuffixL;
result.num_lit_suffix = .L; result.num_lit_suffix = .L;
result.bytes = chars[begin_index .. i.* - 1]; result.bytes = chars[begin_index..i.*];
}, },
else => { else => {
i.* -= 1; i.* -= 1;
@ -425,7 +434,6 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
'0'...'7' => {}, '0'...'7' => {},
'8', '9' => return error.TokenizingFailed, '8', '9' => return error.TokenizingFailed,
else => { else => {
i.* -= 1;
result.bytes = chars[begin_index..i.*]; result.bytes = chars[begin_index..i.*];
return result; return result;
}, },
@ -438,16 +446,15 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
// marks the number literal as unsigned // marks the number literal as unsigned
state = .NumLitIntSuffixU; state = .NumLitIntSuffixU;
result.num_lit_suffix = .U; result.num_lit_suffix = .U;
result.bytes = chars[begin_index .. i.* - 1]; result.bytes = chars[begin_index..i.*];
}, },
'l', 'L' => { 'l', 'L' => {
// marks the number literal as long // marks the number literal as long
state = .NumLitIntSuffixL; state = .NumLitIntSuffixL;
result.num_lit_suffix = .L; result.num_lit_suffix = .L;
result.bytes = chars[begin_index .. i.* - 1]; result.bytes = chars[begin_index..i.*];
}, },
else => { else => {
i.* -= 1;
result.bytes = chars[begin_index..i.*]; result.bytes = chars[begin_index..i.*];
return result; return result;
}, },
@ -461,16 +468,15 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
// marks the number literal as unsigned // marks the number literal as unsigned
state = .NumLitIntSuffixU; state = .NumLitIntSuffixU;
result.num_lit_suffix = .U; result.num_lit_suffix = .U;
result.bytes = chars[begin_index .. i.* - 1]; result.bytes = chars[begin_index..i.*];
}, },
'l', 'L' => { 'l', 'L' => {
// marks the number literal as long // marks the number literal as long
state = .NumLitIntSuffixL; state = .NumLitIntSuffixL;
result.num_lit_suffix = .L; result.num_lit_suffix = .L;
result.bytes = chars[begin_index .. i.* - 1]; result.bytes = chars[begin_index..i.*];
}, },
else => { else => {
i.* -= 1;
result.bytes = chars[begin_index..i.*]; result.bytes = chars[begin_index..i.*];
return result; return result;
}, },
@ -483,7 +489,6 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
state = .NumLitIntSuffixUL; state = .NumLitIntSuffixUL;
}, },
else => { else => {
i.* -= 1;
return result; return result;
}, },
} }
@ -496,10 +501,9 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
}, },
'u', 'U' => { 'u', 'U' => {
result.num_lit_suffix = .LU; result.num_lit_suffix = .LU;
return result; state = .Done;
}, },
else => { else => {
i.* -= 1;
return result; return result;
}, },
} }
@ -508,10 +512,9 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
switch (c) { switch (c) {
'u', 'U' => { 'u', 'U' => {
result.num_lit_suffix = .LLU; result.num_lit_suffix = .LLU;
return result; state = .Done;
}, },
else => { else => {
i.* -= 1;
return result; return result;
}, },
} }
@ -523,7 +526,6 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
return result; return result;
}, },
else => { else => {
i.* -= 1;
return result; return result;
}, },
} }
@ -532,17 +534,16 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
switch (c) { switch (c) {
'_', 'a'...'z', 'A'...'Z', '0'...'9' => {}, '_', 'a'...'z', 'A'...'Z', '0'...'9' => {},
else => { else => {
i.* -= 1;
result.bytes = chars[begin_index..i.*]; result.bytes = chars[begin_index..i.*];
return result; return result;
}, },
} }
}, },
.String => { // TODO char escapes .String => {
switch (c) { switch (c) {
'\"' => { '\"' => {
result.bytes = chars[begin_index..i.*]; result.bytes = chars[begin_index .. i.* + 1];
return result; state = .Done;
}, },
else => {}, else => {},
} }
@ -550,8 +551,8 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
.CharLit => { .CharLit => {
switch (c) { switch (c) {
'\'' => { '\'' => {
result.bytes = chars[begin_index..i.*]; result.bytes = chars[begin_index .. i.* + 1];
return result; state = .Done;
}, },
else => {}, else => {},
} }
@ -566,7 +567,7 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
}, },
else => { else => {
result.id = .Slash; result.id = .Slash;
return result; state = .Done;
}, },
} }
}, },
@ -598,6 +599,7 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
} }
}, },
} }
i.* += 1;
} }
unreachable; unreachable;
} }

View File

@ -1096,5 +1096,9 @@ pub extern fn ZigClangCharacterLiteral_getBeginLoc(*const ZigClangCharacterLiter
pub extern fn ZigClangCharacterLiteral_getKind(*const ZigClangCharacterLiteral) ZigClangCharacterLiteral_CharacterKind; pub extern fn ZigClangCharacterLiteral_getKind(*const ZigClangCharacterLiteral) ZigClangCharacterLiteral_CharacterKind;
pub extern fn ZigClangCharacterLiteral_getValue(*const ZigClangCharacterLiteral) c_uint; pub extern fn ZigClangCharacterLiteral_getValue(*const ZigClangCharacterLiteral) c_uint;
pub extern fn ZigClangStmtExpr_getSubStmt( *const ZigClangStmtExpr) *const ZigClangCompoundStmt; pub extern fn ZigClangStmtExpr_getSubStmt(*const ZigClangStmtExpr) *const ZigClangCompoundStmt;
pub extern fn ZigClangMemberExpr_getBase(*const ZigClangMemberExpr) *const ZigClangExpr;
pub extern fn ZigClangMemberExpr_isArrow(*const ZigClangMemberExpr) bool;
pub extern fn ZigClangMemberExpr_getMemberDecl(*const ZigClangMemberExpr) *const ZigClangValueDecl;

View File

@ -49,9 +49,6 @@ const Scope = struct {
Root, Root,
Condition, Condition,
FnDef, FnDef,
/// used when getting a member `a.b`
Ref,
Loop, Loop,
}; };
@ -181,7 +178,6 @@ const Scope = struct {
fn getAlias(scope: *Scope, name: []const u8) ?[]const u8 { fn getAlias(scope: *Scope, name: []const u8) ?[]const u8 {
return switch (scope.id) { return switch (scope.id) {
.Root => null, .Root => null,
.Ref => null,
.FnDef => @fieldParentPtr(FnDef, "base", scope).getAlias(name), .FnDef => @fieldParentPtr(FnDef, "base", scope).getAlias(name),
.Block => @fieldParentPtr(Block, "base", scope).getAlias(name), .Block => @fieldParentPtr(Block, "base", scope).getAlias(name),
.Switch, .Loop, .Condition => scope.parent.?.getAlias(name), .Switch, .Loop, .Condition => scope.parent.?.getAlias(name),
@ -190,7 +186,6 @@ const Scope = struct {
fn contains(scope: *Scope, name: []const u8) bool { fn contains(scope: *Scope, name: []const u8) bool {
return switch (scope.id) { return switch (scope.id) {
.Ref => false,
.Root => @fieldParentPtr(Root, "base", scope).contains(name), .Root => @fieldParentPtr(Root, "base", scope).contains(name),
.FnDef => @fieldParentPtr(FnDef, "base", scope).contains(name), .FnDef => @fieldParentPtr(FnDef, "base", scope).contains(name),
.Block => @fieldParentPtr(Block, "base", scope).contains(name), .Block => @fieldParentPtr(Block, "base", scope).contains(name),
@ -230,7 +225,6 @@ const Context = struct {
decl_table: DeclTable, decl_table: DeclTable,
alias_list: AliasList, alias_list: AliasList,
global_scope: *Scope.Root, global_scope: *Scope.Root,
ptr_params: std.BufSet,
clang_context: *ZigClangASTContext, clang_context: *ZigClangASTContext,
mangle_count: u64 = 0, mangle_count: u64 = 0,
@ -316,7 +310,6 @@ pub fn translate(
.decl_table = DeclTable.init(arena), .decl_table = DeclTable.init(arena),
.alias_list = AliasList.init(arena), .alias_list = AliasList.init(arena),
.global_scope = try arena.create(Scope.Root), .global_scope = try arena.create(Scope.Root),
.ptr_params = std.BufSet.init(arena),
.clang_context = ZigClangASTUnit_getASTContext(ast_unit).?, .clang_context = ZigClangASTUnit_getASTContext(ast_unit).?,
}; };
context.global_scope.* = Scope.Root.init(&context); context.global_scope.* = Scope.Root.init(&context);
@ -856,6 +849,7 @@ fn transStmt(
.PredefinedExprClass => return transPredefinedExpr(rp, scope, @ptrCast(*const ZigClangPredefinedExpr, stmt), result_used), .PredefinedExprClass => return transPredefinedExpr(rp, scope, @ptrCast(*const ZigClangPredefinedExpr, stmt), result_used),
.CharacterLiteralClass => return transCharLiteral(rp, scope, @ptrCast(*const ZigClangCharacterLiteral, stmt), result_used), .CharacterLiteralClass => return transCharLiteral(rp, scope, @ptrCast(*const ZigClangCharacterLiteral, stmt), result_used),
.StmtExprClass => return transStmtExpr(rp, scope, @ptrCast(*const ZigClangStmtExpr, stmt), result_used), .StmtExprClass => return transStmtExpr(rp, scope, @ptrCast(*const ZigClangStmtExpr, stmt), result_used),
.MemberExprClass => return transMemberExpr(rp, scope, @ptrCast(*const ZigClangMemberExpr, stmt), result_used),
else => { else => {
return revertAndWarn( return revertAndWarn(
rp, rp,
@ -1147,7 +1141,6 @@ fn transDeclRefExpr(
const value_decl = ZigClangDeclRefExpr_getDecl(expr); const value_decl = ZigClangDeclRefExpr_getDecl(expr);
const name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, value_decl))); const name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, value_decl)));
const checked_name = if (scope.getAlias(name)) |a| a else name; const checked_name = if (scope.getAlias(name)) |a| a else name;
if (lrvalue == .l_value) try rp.c.ptr_params.put(checked_name);
return transCreateNodeIdentifier(rp.c, checked_name); return transCreateNodeIdentifier(rp.c, checked_name);
} }
@ -1990,6 +1983,18 @@ fn transStmtExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangStmtExpr,
return maybeSuppressResult(rp, scope, used, &grouped_expr.base); return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
} }
fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangMemberExpr, result_used: ResultUsed) TransError!*ast.Node {
var container_node = try transExpr(rp, scope, ZigClangMemberExpr_getBase(stmt), .used, .r_value);
if (ZigClangMemberExpr_isArrow(stmt)) {
container_node = try transCreateNodePtrDeref(rp.c, container_node);
}
const name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, ZigClangMemberExpr_getMemberDecl(stmt))));
const node = try transCreateNodeFieldAccess(rp.c, container_node, name);
return maybeSuppressResult(rp, scope, result_used, node);
}
fn transCPtrCast( fn transCPtrCast(
rp: RestorePoint, rp: RestorePoint,
loc: ZigClangSourceLocation, loc: ZigClangSourceLocation,
@ -2213,8 +2218,8 @@ fn qualTypeToLog2IntRef(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigC
import_fn_call.rparen_token = try appendToken(rp.c, .RParen, ")"); import_fn_call.rparen_token = try appendToken(rp.c, .RParen, ")");
const inner_field_access = try transCreateNodeFieldAccess(rp.c, &import_fn_call.base, "math"); const inner_field_access = try transCreateNodeFieldAccess(rp.c, &import_fn_call.base, "math");
const outer_field_access = try transCreateNodeFieldAccess(rp.c, &inner_field_access.base, "Log2Int"); const outer_field_access = try transCreateNodeFieldAccess(rp.c, inner_field_access, "Log2Int");
const log2int_fn_call = try transCreateNodeFnCall(rp.c, &outer_field_access.base); const log2int_fn_call = try transCreateNodeFnCall(rp.c, outer_field_access);
try @ptrCast(*ast.Node.SuffixOp.Op.Call, &log2int_fn_call.op).params.push(zig_type_node); try @ptrCast(*ast.Node.SuffixOp.Op.Call, &log2int_fn_call.op).params.push(zig_type_node);
log2int_fn_call.rtoken = try appendToken(rp.c, .RParen, ")"); log2int_fn_call.rtoken = try appendToken(rp.c, .RParen, ")");
@ -2446,7 +2451,7 @@ fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp {
return node; return node;
} }
fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []const u8) !*ast.Node.InfixOp { fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []const u8) !*ast.Node {
const field_access_node = try c.a().create(ast.Node.InfixOp); const field_access_node = try c.a().create(ast.Node.InfixOp);
field_access_node.* = .{ field_access_node.* = .{
.op_token = try appendToken(c, .Period, "."), .op_token = try appendToken(c, .Period, "."),
@ -2454,7 +2459,7 @@ fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []c
.op = .Period, .op = .Period,
.rhs = try transCreateNodeIdentifier(c, field_name), .rhs = try transCreateNodeIdentifier(c, field_name),
}; };
return field_access_node; return &field_access_node.base;
} }
fn transCreateNodePrefixOp( fn transCreateNodePrefixOp(
@ -2924,9 +2929,9 @@ fn transCreateNodeShiftOp(
rp: RestorePoint, rp: RestorePoint,
scope: *Scope, scope: *Scope,
stmt: *const ZigClangBinaryOperator, stmt: *const ZigClangBinaryOperator,
comptime op: ast.Node.InfixOp.Op, op: ast.Node.InfixOp.Op,
comptime op_tok_id: std.zig.Token.Id, op_tok_id: std.zig.Token.Id,
comptime bytes: []const u8, bytes: []const u8,
) !*ast.Node { ) !*ast.Node {
std.debug.assert(op == .BitShiftLeft or op == .BitShiftRight); std.debug.assert(op == .BitShiftLeft or op == .BitShiftRight);
@ -2957,6 +2962,16 @@ fn transCreateNodeShiftOp(
return &node.base; return &node.base;
} }
fn transCreateNodePtrDeref(c: *Context, lhs: *ast.Node) !*ast.Node {
const node = try c.a().create(ast.Node.SuffixOp);
node.* = .{
.lhs = .{ .node = lhs },
.op = .Deref,
.rtoken = try appendToken(c, .PeriodAsterisk, ".*"),
};
return &node.base;
}
const RestorePoint = struct { const RestorePoint = struct {
c: *Context, c: *Context,
token_index: ast.TokenIndex, token_index: ast.TokenIndex,
@ -3862,16 +3877,21 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
.{}, .{},
); );
const op_token = try appendToken(rp.c, .Period, "."); node = try transCreateNodeFieldAccess(rp.c, node, name_tok.bytes);
const rhs = try transCreateNodeIdentifier(rp.c, name_tok.bytes); },
const access_node = try rp.c.a().create(ast.Node.InfixOp); .Arrow => {
access_node.* = .{ const name_tok = it.next().?;
.op_token = op_token, if (name_tok.id != .Identifier)
.lhs = node, return revertAndWarn(
.op = .Period, rp,
.rhs = rhs, error.ParseError,
}; source_loc,
node = &access_node.base; "unable to translate C expr",
.{},
);
const deref = try transCreateNodePtrDeref(rp.c, node);
node = try transCreateNodeFieldAccess(rp.c, deref, name_tok.bytes);
}, },
.Asterisk => { .Asterisk => {
if (it.peek().?.id == .RParen) { if (it.peek().?.id == .RParen) {
@ -3887,14 +3907,14 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
// expr * expr // expr * expr
const op_token = try appendToken(rp.c, .Asterisk, "*"); const op_token = try appendToken(rp.c, .Asterisk, "*");
const rhs = try parseCPrimaryExpr(rp, it, source_loc, scope); const rhs = try parseCPrimaryExpr(rp, it, source_loc, scope);
const bitshift_node = try rp.c.a().create(ast.Node.InfixOp); const mul_node = try rp.c.a().create(ast.Node.InfixOp);
bitshift_node.* = .{ mul_node.* = .{
.op_token = op_token, .op_token = op_token,
.lhs = node, .lhs = node,
.op = .BitShiftLeft, .op = .BitShiftLeft,
.rhs = rhs, .rhs = rhs,
}; };
node = &bitshift_node.base; node = &mul_node.base;
} }
}, },
.Shl => { .Shl => {
@ -3938,13 +3958,7 @@ fn parseCPrefixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
}, },
.Asterisk => { .Asterisk => {
const prefix_op_expr = try parseCPrefixOpExpr(rp, it, source_loc, scope); const prefix_op_expr = try parseCPrefixOpExpr(rp, it, source_loc, scope);
const node = try rp.c.a().create(ast.Node.SuffixOp); return try transCreateNodePtrDeref(rp.c, prefix_op_expr);
node.* = .{
.lhs = .{ .node = prefix_op_expr },
.op = .Deref,
.rtoken = try appendToken(rp.c, .PeriodAsterisk, ".*"),
};
return &node.base;
}, },
else => { else => {
_ = it.prev(); _ = it.prev();

View File

@ -1494,6 +1494,35 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\} \\}
}); });
cases.add_2("field access expression",
\\#define ARROW a->b
\\#define DOT a.b
\\extern struct Foo {
\\ int b;
\\}a;
\\float b = 2.0f;
\\int foo(void) {
\\ struct Foo *c;
\\ a.b;
\\ c->b;
\\}
, &[_][]const u8{
\\pub const struct_Foo = extern struct {
\\ b: c_int,
\\};
\\pub extern var a: struct_Foo;
\\pub export var b: f32 = 2;
\\pub export fn foo() c_int {
\\ var c: [*c]struct_Foo = undefined;
\\ _ = a.b;
\\ _ = c.*.b;
\\}
,
\\pub const DOT = a.b;
,
\\pub const ARROW = a.*.b;
});
/////////////// Cases for only stage1 which are TODO items for stage2 //////////////// /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
cases.addAllowWarnings("simple data types", cases.addAllowWarnings("simple data types",
@ -1702,22 +1731,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\} \\}
}); });
cases.addC("field access expression",
\\struct Foo {
\\ int field;
\\};
\\int read_field(struct Foo *foo) {
\\ return foo->field;
\\}
, &[_][]const u8{
\\pub const struct_Foo = extern struct {
\\ field: c_int,
\\};
\\pub export fn read_field(foo: [*c]struct_Foo) c_int {
\\ return foo.*.field;
\\}
});
cases.addC("array access", cases.addC("array access",
\\int array[100]; \\int array[100];
\\int foo(int index) { \\int foo(int index) {
@ -2627,4 +2640,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ }; \\ };
\\} \\}
}); });
cases.addC("field access expression",
\\struct Foo {
\\ int field;
\\};
\\int read_field(struct Foo *foo) {
\\ return foo->field;
\\}
, &[_][]const u8{
\\pub const struct_Foo = extern struct {
\\ field: c_int,
\\};
\\pub export fn read_field(foo: [*c]struct_Foo) c_int {
\\ return foo.*.field;
\\}
});
} }