Skip to content

Commit 76ab1d2

Browse files
committed
support foo.* for ptr deref
See #770
1 parent e14db23 commit 76ab1d2

File tree

8 files changed

+69
-10
lines changed

8 files changed

+69
-10
lines changed

doc/langref.html.in

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5958,10 +5958,12 @@ MultiplyOperator = "||" | "*" | "/" | "%" | "**" | "*%"
59585958

59595959
PrefixOpExpression = PrefixOp TypeExpr | SuffixOpExpression
59605960

5961-
SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
5961+
SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | PtrDerefExpression)
59625962

59635963
FieldAccessExpression = "." Symbol
59645964

5965+
PtrDerefExpression = ".*"
5966+
59655967
FnCallExpression = "(" list(Expression, ",") ")"
59665968

59675969
ArrayAccessExpression = "[" Expression "]"
@@ -5974,7 +5976,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")
59745976

59755977
StructLiteralField = "." Symbol "=" Expression
59765978

5977-
PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
5979+
PrefixOp = "!" | "-" | "~" | ("*" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
59785980

59795981
PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType
59805982

src/all_types.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ enum NodeType {
379379
NodeTypeArrayAccessExpr,
380380
NodeTypeSliceExpr,
381381
NodeTypeFieldAccessExpr,
382+
NodeTypePtrDeref,
382383
NodeTypeUse,
383384
NodeTypeBoolLiteral,
384385
NodeTypeNullLiteral,
@@ -603,6 +604,10 @@ struct AstNodeFieldAccessExpr {
603604
Buf *field_name;
604605
};
605606

607+
struct AstNodePtrDerefExpr {
608+
AstNode *target;
609+
};
610+
606611
enum PrefixOp {
607612
PrefixOpInvalid,
608613
PrefixOpBoolNot,
@@ -911,6 +916,7 @@ struct AstNode {
911916
AstNodeCompTime comptime_expr;
912917
AstNodeAsmExpr asm_expr;
913918
AstNodeFieldAccessExpr field_access_expr;
919+
AstNodePtrDerefExpr ptr_deref_expr;
914920
AstNodeContainerDecl container_decl;
915921
AstNodeStructField struct_field;
916922
AstNodeStringLiteral string_literal;

src/analyze.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3275,6 +3275,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
32753275
case NodeTypeUnreachable:
32763276
case NodeTypeAsmExpr:
32773277
case NodeTypeFieldAccessExpr:
3278+
case NodeTypePtrDeref:
32783279
case NodeTypeStructField:
32793280
case NodeTypeContainerInitExpr:
32803281
case NodeTypeStructValueField:

src/ast_render.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ static const char *node_type_str(NodeType node_type) {
222222
return "AsmExpr";
223223
case NodeTypeFieldAccessExpr:
224224
return "FieldAccessExpr";
225+
case NodeTypePtrDeref:
226+
return "PtrDerefExpr";
225227
case NodeTypeContainerDecl:
226228
return "ContainerDecl";
227229
case NodeTypeStructField:
@@ -696,6 +698,13 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
696698
print_symbol(ar, rhs);
697699
break;
698700
}
701+
case NodeTypePtrDeref:
702+
{
703+
AstNode *lhs = node->data.ptr_deref_expr.target;
704+
render_node_ungrouped(ar, lhs);
705+
fprintf(ar->f, ".*");
706+
break;
707+
}
699708
case NodeTypeUndefinedLiteral:
700709
fprintf(ar->f, "undefined");
701710
break;

src/ir.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4548,8 +4548,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
45484548
}
45494549

45504550
static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) {
4551-
assert(node->type == NodeTypePrefixOpExpr);
4552-
AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
4551+
AstNode *expr_node;
4552+
if (node->type == NodeTypePrefixOpExpr) {
4553+
expr_node = node->data.prefix_op_expr.primary_expr;
4554+
} else if (node->type == NodeTypePtrDeref) {
4555+
expr_node = node->data.ptr_deref_expr.target;
4556+
} else {
4557+
zig_unreachable();
4558+
}
45534559

45544560
IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval);
45554561
if (value == irb->codegen->invalid_instruction)
@@ -6527,6 +6533,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
65276533

65286534
return ir_build_load_ptr(irb, scope, node, ptr_instruction);
65296535
}
6536+
case NodeTypePtrDeref:
6537+
return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval);
65306538
case NodeTypeThisLiteral:
65316539
return ir_lval_wrap(irb, scope, ir_gen_this_literal(irb, scope, node), lval);
65326540
case NodeTypeBoolLiteral:

src/parser.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,11 +1046,12 @@ static AstNode *ast_parse_fn_proto_partial(ParseContext *pc, size_t *token_index
10461046
}
10471047

10481048
/*
1049-
SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
1049+
SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | PtrDerefExpression | SliceExpression)
10501050
FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
10511051
ArrayAccessExpression : token(LBracket) Expression token(RBracket)
10521052
SliceExpression = "[" Expression ".." option(Expression) "]"
10531053
FieldAccessExpression : token(Dot) token(Symbol)
1054+
PtrDerefExpression = ".*"
10541055
StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression
10551056
*/
10561057
static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
@@ -1131,13 +1132,27 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index,
11311132
} else if (first_token->id == TokenIdDot) {
11321133
*token_index += 1;
11331134

1134-
Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
1135+
Token *token = &pc->tokens->at(*token_index);
1136+
1137+
if (token->id == TokenIdSymbol) {
1138+
*token_index += 1;
11351139

1136-
AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, first_token);
1137-
node->data.field_access_expr.struct_expr = primary_expr;
1138-
node->data.field_access_expr.field_name = token_buf(name_token);
1140+
AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, first_token);
1141+
node->data.field_access_expr.struct_expr = primary_expr;
1142+
node->data.field_access_expr.field_name = token_buf(token);
1143+
1144+
primary_expr = node;
1145+
} else if (token->id == TokenIdStar) {
1146+
*token_index += 1;
1147+
1148+
AstNode *node = ast_create_node(pc, NodeTypePtrDeref, first_token);
1149+
node->data.ptr_deref_expr.target = primary_expr;
1150+
1151+
primary_expr = node;
1152+
} else {
1153+
ast_invalid_token_error(pc, token);
1154+
}
11391155

1140-
primary_expr = node;
11411156
} else {
11421157
return primary_expr;
11431158
}
@@ -3012,6 +3027,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
30123027
case NodeTypeFieldAccessExpr:
30133028
visit_field(&node->data.field_access_expr.struct_expr, visit, context);
30143029
break;
3030+
case NodeTypePtrDeref:
3031+
visit_field(&node->data.ptr_deref_expr.target, visit, context);
3032+
break;
30153033
case NodeTypeUse:
30163034
visit_field(&node->data.use.expr, visit, context);
30173035
break;

test/behavior.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ comptime {
3333
_ = @import("cases/misc.zig");
3434
_ = @import("cases/namespace_depends_on_compile_var/index.zig");
3535
_ = @import("cases/null.zig");
36+
_ = @import("cases/pointers.zig");
3637
_ = @import("cases/pub_enum/index.zig");
3738
_ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
3839
_ = @import("cases/reflection.zig");

test/cases/pointers.zig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const std = @import("std");
2+
const assert = std.debug.assert;
3+
4+
test "dereference pointer" {
5+
comptime testDerefPtr();
6+
testDerefPtr();
7+
}
8+
9+
fn testDerefPtr() void {
10+
var x: i32 = 1234;
11+
var y = &x;
12+
y.* += 1;
13+
assert(x == 1235);
14+
}

0 commit comments

Comments
 (0)