| author | |
| committer | |
| log | 76ab1d2b6c9eedd861920ae6b6f8ee06aa482159 |
| tree | 225b147c84541b41d9f7a0f640c1e905000ee357 |
| parent | e14db2366160840e0c25f3a467ff984304831e4c |
See #7708 files changed, 69 insertions(+), 10 deletions(-)
doc/langref.html.in+4-2| ... | ... | @@ -5958,10 +5958,12 @@ MultiplyOperator = "||" | "*" | "/" | "%" | "**" | "*%" |
| 5958 | 5958 | |
| 5959 | 5959 | PrefixOpExpression = PrefixOp TypeExpr | SuffixOpExpression |
| 5960 | 5960 | |
| 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) | |
| 5962 | 5962 | |
| 5963 | 5963 | FieldAccessExpression = "." Symbol |
| 5964 | 5964 | |
| 5965 | PtrDerefExpression = ".*" | |
| 5966 | ||
| 5965 | 5967 | FnCallExpression = "(" list(Expression, ",") ")" |
| 5966 | 5968 | |
| 5967 | 5969 | ArrayAccessExpression = "[" Expression "]" |
| ... | ... | @@ -5974,7 +5976,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",") |
| 5974 | 5976 | |
| 5975 | 5977 | StructLiteralField = "." Symbol "=" Expression |
| 5976 | 5978 | |
| 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" | |
| 5978 | 5980 | |
| 5979 | 5981 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType |
| 5980 | 5982 |
src/all_types.hpp+6| ... | ... | @@ -379,6 +379,7 @@ enum NodeType { |
| 379 | 379 | NodeTypeArrayAccessExpr, |
| 380 | 380 | NodeTypeSliceExpr, |
| 381 | 381 | NodeTypeFieldAccessExpr, |
| 382 | NodeTypePtrDeref, | |
| 382 | 383 | NodeTypeUse, |
| 383 | 384 | NodeTypeBoolLiteral, |
| 384 | 385 | NodeTypeNullLiteral, |
| ... | ... | @@ -603,6 +604,10 @@ struct AstNodeFieldAccessExpr { |
| 603 | 604 | Buf *field_name; |
| 604 | 605 | }; |
| 605 | 606 | |
| 607 | struct AstNodePtrDerefExpr { | |
| 608 | AstNode *target; | |
| 609 | }; | |
| 610 | ||
| 606 | 611 | enum PrefixOp { |
| 607 | 612 | PrefixOpInvalid, |
| 608 | 613 | PrefixOpBoolNot, |
| ... | ... | @@ -911,6 +916,7 @@ struct AstNode { |
| 911 | 916 | AstNodeCompTime comptime_expr; |
| 912 | 917 | AstNodeAsmExpr asm_expr; |
| 913 | 918 | AstNodeFieldAccessExpr field_access_expr; |
| 919 | AstNodePtrDerefExpr ptr_deref_expr; | |
| 914 | 920 | AstNodeContainerDecl container_decl; |
| 915 | 921 | AstNodeStructField struct_field; |
| 916 | 922 | AstNodeStringLiteral string_literal; |
src/analyze.cpp+1| ... | ... | @@ -3275,6 +3275,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 3275 | 3275 | case NodeTypeUnreachable: |
| 3276 | 3276 | case NodeTypeAsmExpr: |
| 3277 | 3277 | case NodeTypeFieldAccessExpr: |
| 3278 | case NodeTypePtrDeref: | |
| 3278 | 3279 | case NodeTypeStructField: |
| 3279 | 3280 | case NodeTypeContainerInitExpr: |
| 3280 | 3281 | case NodeTypeStructValueField: |
src/ast_render.cpp+9| ... | ... | @@ -222,6 +222,8 @@ static const char *node_type_str(NodeType node_type) { |
| 222 | 222 | return "AsmExpr"; |
| 223 | 223 | case NodeTypeFieldAccessExpr: |
| 224 | 224 | return "FieldAccessExpr"; |
| 225 | case NodeTypePtrDeref: | |
| 226 | return "PtrDerefExpr"; | |
| 225 | 227 | case NodeTypeContainerDecl: |
| 226 | 228 | return "ContainerDecl"; |
| 227 | 229 | case NodeTypeStructField: |
| ... | ... | @@ -696,6 +698,13 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 696 | 698 | print_symbol(ar, rhs); |
| 697 | 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 | 708 | case NodeTypeUndefinedLiteral: |
| 700 | 709 | fprintf(ar->f, "undefined"); |
| 701 | 710 | break; |
src/ir.cpp+10-2| ... | ... | @@ -4548,8 +4548,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode |
| 4548 | 4548 | } |
| 4549 | 4549 | |
| 4550 | 4550 | 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 | } | |
| 4553 | 4559 | |
| 4554 | 4560 | IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval); |
| 4555 | 4561 | if (value == irb->codegen->invalid_instruction) |
| ... | ... | @@ -6527,6 +6533,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 6527 | 6533 | |
| 6528 | 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 | 6538 | case NodeTypeThisLiteral: |
| 6531 | 6539 | return ir_lval_wrap(irb, scope, ir_gen_this_literal(irb, scope, node), lval); |
| 6532 | 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 | 1046 | } |
| 1047 | 1047 | |
| 1048 | 1048 | /* |
| 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) | |
| 1050 | 1050 | FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen) |
| 1051 | 1051 | ArrayAccessExpression : token(LBracket) Expression token(RBracket) |
| 1052 | 1052 | SliceExpression = "[" Expression ".." option(Expression) "]" |
| 1053 | 1053 | FieldAccessExpression : token(Dot) token(Symbol) |
| 1054 | PtrDerefExpression = ".*" | |
| 1054 | 1055 | StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression |
| 1055 | 1056 | */ |
| 1056 | 1057 | 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, |
| 1131 | 1132 | } else if (first_token->id == TokenIdDot) { |
| 1132 | 1133 | *token_index += 1; |
| 1133 | 1134 | |
| 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; | |
| 1135 | 1139 | |
| 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 | } | |
| 1139 | 1155 | |
| 1140 | primary_expr = node; | |
| 1141 | 1156 | } else { |
| 1142 | 1157 | return primary_expr; |
| 1143 | 1158 | } |
| ... | ... | @@ -3012,6 +3027,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 3012 | 3027 | case NodeTypeFieldAccessExpr: |
| 3013 | 3028 | visit_field(&node->data.field_access_expr.struct_expr, visit, context); |
| 3014 | 3029 | break; |
| 3030 | case NodeTypePtrDeref: | |
| 3031 | visit_field(&node->data.ptr_deref_expr.target, visit, context); | |
| 3032 | break; | |
| 3015 | 3033 | case NodeTypeUse: |
| 3016 | 3034 | visit_field(&node->data.use.expr, visit, context); |
| 3017 | 3035 | break; |
test/behavior.zig+1| ... | ... | @@ -33,6 +33,7 @@ comptime { |
| 33 | 33 | _ = @import("cases/misc.zig"); |
| 34 | 34 | _ = @import("cases/namespace_depends_on_compile_var/index.zig"); |
| 35 | 35 | _ = @import("cases/null.zig"); |
| 36 | _ = @import("cases/pointers.zig"); | |
| 36 | 37 | _ = @import("cases/pub_enum/index.zig"); |
| 37 | 38 | _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); |
| 38 | 39 | _ = @import("cases/reflection.zig"); |
test/cases/pointers.zig created+14| ... | ... | @@ -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 | } |