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 = "||" | "*" | "/" | "%" | "**" | "*%"...@@ -5958,10 +5958,12 @@ MultiplyOperator = "||" | "*" | "/" | "%" | "**" | "*%"
59585958
5959PrefixOpExpression = PrefixOp TypeExpr | SuffixOpExpression5959PrefixOpExpression = 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
5963FieldAccessExpression = "." Symbol5963FieldAccessExpression = "." Symbol
59645964
5965PtrDerefExpression = ".*"
5966
5965FnCallExpression = "(" list(Expression, ",") ")"5967FnCallExpression = "(" list(Expression, ",") ")"
59665968
5967ArrayAccessExpression = "[" Expression "]"5969ArrayAccessExpression = "[" Expression "]"
...@@ -5974,7 +5976,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")...@@ -5974,7 +5976,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")
59745976
5975StructLiteralField = "." Symbol "=" Expression5977StructLiteralField = "." 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
5979PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType5981PrimaryExpression = 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 {...@@ -379,6 +379,7 @@ enum NodeType {
379 NodeTypeArrayAccessExpr,379 NodeTypeArrayAccessExpr,
380 NodeTypeSliceExpr,380 NodeTypeSliceExpr,
381 NodeTypeFieldAccessExpr,381 NodeTypeFieldAccessExpr,
382 NodeTypePtrDeref,
382 NodeTypeUse,383 NodeTypeUse,
383 NodeTypeBoolLiteral,384 NodeTypeBoolLiteral,
384 NodeTypeNullLiteral,385 NodeTypeNullLiteral,
...@@ -603,6 +604,10 @@ struct AstNodeFieldAccessExpr {...@@ -603,6 +604,10 @@ struct AstNodeFieldAccessExpr {
603 Buf *field_name;604 Buf *field_name;
604};605};
605606
607struct AstNodePtrDerefExpr {
608 AstNode *target;
609};
610
606enum PrefixOp {611enum PrefixOp {
607 PrefixOpInvalid,612 PrefixOpInvalid,
608 PrefixOpBoolNot,613 PrefixOpBoolNot,
...@@ -911,6 +916,7 @@ struct AstNode {...@@ -911,6 +916,7 @@ struct AstNode {
911 AstNodeCompTime comptime_expr;916 AstNodeCompTime comptime_expr;
912 AstNodeAsmExpr asm_expr;917 AstNodeAsmExpr asm_expr;
913 AstNodeFieldAccessExpr field_access_expr;918 AstNodeFieldAccessExpr field_access_expr;
919 AstNodePtrDerefExpr ptr_deref_expr;
914 AstNodeContainerDecl container_decl;920 AstNodeContainerDecl container_decl;
915 AstNodeStructField struct_field;921 AstNodeStructField struct_field;
916 AstNodeStringLiteral string_literal;922 AstNodeStringLiteral string_literal;
src/analyze.cpp+1
...@@ -3275,6 +3275,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -3275,6 +3275,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
3275 case NodeTypeUnreachable:3275 case NodeTypeUnreachable:
3276 case NodeTypeAsmExpr:3276 case NodeTypeAsmExpr:
3277 case NodeTypeFieldAccessExpr:3277 case NodeTypeFieldAccessExpr:
3278 case NodeTypePtrDeref:
3278 case NodeTypeStructField:3279 case NodeTypeStructField:
3279 case NodeTypeContainerInitExpr:3280 case NodeTypeContainerInitExpr:
3280 case NodeTypeStructValueField:3281 case NodeTypeStructValueField:
src/ast_render.cpp+9
...@@ -222,6 +222,8 @@ static const char *node_type_str(NodeType node_type) {...@@ -222,6 +222,8 @@ static const char *node_type_str(NodeType node_type) {
222 return "AsmExpr";222 return "AsmExpr";
223 case NodeTypeFieldAccessExpr:223 case NodeTypeFieldAccessExpr:
224 return "FieldAccessExpr";224 return "FieldAccessExpr";
225 case NodeTypePtrDeref:
226 return "PtrDerefExpr";
225 case NodeTypeContainerDecl:227 case NodeTypeContainerDecl:
226 return "ContainerDecl";228 return "ContainerDecl";
227 case NodeTypeStructField:229 case NodeTypeStructField:
...@@ -696,6 +698,13 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -696,6 +698,13 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
696 print_symbol(ar, rhs);698 print_symbol(ar, rhs);
697 break;699 break;
698 }700 }
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 }
699 case NodeTypeUndefinedLiteral:708 case NodeTypeUndefinedLiteral:
700 fprintf(ar->f, "undefined");709 fprintf(ar->f, "undefined");
701 break;710 break;
src/ir.cpp+10-2
...@@ -4548,8 +4548,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -4548,8 +4548,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
4548}4548}
45494549
4550static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) {4550static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) {
4551 assert(node->type == NodeTypePrefixOpExpr);4551 AstNode *expr_node;
4552 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;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
4554 IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval);4560 IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval);
4555 if (value == irb->codegen->invalid_instruction)4561 if (value == irb->codegen->invalid_instruction)
...@@ -6527,6 +6533,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -6527,6 +6533,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
65276533
6528 return ir_build_load_ptr(irb, scope, node, ptr_instruction);6534 return ir_build_load_ptr(irb, scope, node, ptr_instruction);
6529 }6535 }
6536 case NodeTypePtrDeref:
6537 return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval);
6530 case NodeTypeThisLiteral:6538 case NodeTypeThisLiteral:
6531 return ir_lval_wrap(irb, scope, ir_gen_this_literal(irb, scope, node), lval);6539 return ir_lval_wrap(irb, scope, ir_gen_this_literal(irb, scope, node), lval);
6532 case NodeTypeBoolLiteral:6540 case NodeTypeBoolLiteral:
src/parser.cpp+24-6
...@@ -1046,11 +1046,12 @@ static AstNode *ast_parse_fn_proto_partial(ParseContext *pc, size_t *token_index...@@ -1046,11 +1046,12 @@ static AstNode *ast_parse_fn_proto_partial(ParseContext *pc, size_t *token_index
1046}1046}
10471047
1048/*1048/*
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)
1050FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)1050FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
1051ArrayAccessExpression : token(LBracket) Expression token(RBracket)1051ArrayAccessExpression : token(LBracket) Expression token(RBracket)
1052SliceExpression = "[" Expression ".." option(Expression) "]"1052SliceExpression = "[" Expression ".." option(Expression) "]"
1053FieldAccessExpression : token(Dot) token(Symbol)1053FieldAccessExpression : token(Dot) token(Symbol)
1054PtrDerefExpression = ".*"
1054StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression1055StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression
1055*/1056*/
1056static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {1057static 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,...@@ -1131,13 +1132,27 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index,
1131 } else if (first_token->id == TokenIdDot) {1132 } else if (first_token->id == TokenIdDot) {
1132 *token_index += 1;1133 *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);1140 AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, first_token);
1137 node->data.field_access_expr.struct_expr = primary_expr;1141 node->data.field_access_expr.struct_expr = primary_expr;
1138 node->data.field_access_expr.field_name = token_buf(name_token);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;
1141 } else {1156 } else {
1142 return primary_expr;1157 return primary_expr;
1143 }1158 }
...@@ -3012,6 +3027,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -3012,6 +3027,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
3012 case NodeTypeFieldAccessExpr:3027 case NodeTypeFieldAccessExpr:
3013 visit_field(&node->data.field_access_expr.struct_expr, visit, context);3028 visit_field(&node->data.field_access_expr.struct_expr, visit, context);
3014 break;3029 break;
3030 case NodeTypePtrDeref:
3031 visit_field(&node->data.ptr_deref_expr.target, visit, context);
3032 break;
3015 case NodeTypeUse:3033 case NodeTypeUse:
3016 visit_field(&node->data.use.expr, visit, context);3034 visit_field(&node->data.use.expr, visit, context);
3017 break;3035 break;
test/behavior.zig+1
...@@ -33,6 +33,7 @@ comptime {...@@ -33,6 +33,7 @@ comptime {
33 _ = @import("cases/misc.zig");33 _ = @import("cases/misc.zig");
34 _ = @import("cases/namespace_depends_on_compile_var/index.zig");34 _ = @import("cases/namespace_depends_on_compile_var/index.zig");
35 _ = @import("cases/null.zig");35 _ = @import("cases/null.zig");
36 _ = @import("cases/pointers.zig");
36 _ = @import("cases/pub_enum/index.zig");37 _ = @import("cases/pub_enum/index.zig");
37 _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");38 _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
38 _ = @import("cases/reflection.zig");39 _ = @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}