authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-30 14:20:56-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-30 14:20:56-04:00
log76ab1d2b6c9eedd861920ae6b6f8ee06aa482159
tree225b147c84541b41d9f7a0f640c1e905000ee357
parente14db2366160840e0c25f3a467ff984304831e4c

support foo.* for ptr deref

See #770

8 files changed, 69 insertions(+), 10 deletions(-)

doc/langref.html.in+4-2
......@@ -5958,10 +5958,12 @@ MultiplyOperator = "||" | "*" | "/" | "%" | "**" | "*%"
59585958
59595959PrefixOpExpression = PrefixOp TypeExpr | SuffixOpExpression
59605960
5961SuffixOpExpression = ("async" option("&lt;" SuffixOpExpression "&gt;") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
5961SuffixOpExpression = ("async" option("&lt;" SuffixOpExpression "&gt;") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | PtrDerefExpression)
59625962
59635963FieldAccessExpression = "." Symbol
59645964
5965PtrDerefExpression = ".*"
5966
59655967FnCallExpression = "(" list(Expression, ",") ")"
59665968
59675969ArrayAccessExpression = "[" Expression "]"
......@@ -5974,7 +5976,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")
59745976
59755977StructLiteralField = "." Symbol "=" Expression
59765978
5977PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
5979PrefixOp = "!" | "-" | "~" | ("*" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
59785980
59795981PrimaryExpression = 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+6
......@@ -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
607struct AstNodePtrDerefExpr {
608 AstNode *target;
609};
610
606611enum 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+1
......@@ -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+9
......@@ -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+10-2
......@@ -4548,8 +4548,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
45484548}
45494549
45504550static 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+24-6
......@@ -1046,11 +1046,12 @@ static AstNode *ast_parse_fn_proto_partial(ParseContext *pc, size_t *token_index
10461046}
10471047
10481048/*
1049SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
1049SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | PtrDerefExpression | SliceExpression)
10501050FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
10511051ArrayAccessExpression : token(LBracket) Expression token(RBracket)
10521052SliceExpression = "[" Expression ".." option(Expression) "]"
10531053FieldAccessExpression : token(Dot) token(Symbol)
1054PtrDerefExpression = ".*"
10541055StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression
10551056*/
10561057static 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+1
......@@ -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 created+14
......@@ -0,0 +1,14 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "dereference pointer" {
5 comptime testDerefPtr();
6 testDerefPtr();
7}
8
9fn testDerefPtr() void {
10 var x: i32 = 1234;
11 var y = &x;
12 y.* += 1;
13 assert(x == 1235);
14}