| 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,10 +5958,12 @@ MultiplyOperator = "||" | "*" | "/" | "%" | "**" | "*%" |
| 5958 | 5958 | ||
| 5959 | PrefixOpExpression = PrefixOp TypeExpr | SuffixOpExpression | 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 | FieldAccessExpression = "." Symbol | 5963 | FieldAccessExpression = "." Symbol |
| 5964 | 5964 | ||
| 5965 | PtrDerefExpression = ".*" | ||
| 5966 | |||
| 5965 | FnCallExpression = "(" list(Expression, ",") ")" | 5967 | FnCallExpression = "(" list(Expression, ",") ")" |
| 5966 | 5968 | ||
| 5967 | ArrayAccessExpression = "[" Expression "]" | 5969 | ArrayAccessExpression = "[" Expression "]" |
| ... | @@ -5974,7 +5976,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",") | ... | @@ -5974,7 +5976,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",") |
| 5974 | 5976 | ||
| 5975 | StructLiteralField = "." Symbol "=" Expression | 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 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType | 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,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 | }; |
| 605 | 606 | ||
| 607 | struct AstNodePtrDerefExpr { | ||
| 608 | AstNode *target; | ||
| 609 | }; | ||
| 610 | |||
| 606 | enum PrefixOp { | 611 | enum 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 | } |
| 4549 | 4549 | ||
| 4550 | static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) { | 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); | 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 | } | ||
| 4553 | 4559 | ||
| 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 |
| 6527 | 6533 | ||
| 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 | } |
| 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 | FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen) | 1050 | FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen) |
| 1051 | ArrayAccessExpression : token(LBracket) Expression token(RBracket) | 1051 | ArrayAccessExpression : token(LBracket) Expression token(RBracket) |
| 1052 | SliceExpression = "[" Expression ".." option(Expression) "]" | 1052 | SliceExpression = "[" Expression ".." option(Expression) "]" |
| 1053 | FieldAccessExpression : token(Dot) token(Symbol) | 1053 | FieldAccessExpression : token(Dot) token(Symbol) |
| 1054 | PtrDerefExpression = ".*" | ||
| 1054 | StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression | 1055 | StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression |
| 1055 | */ | 1056 | */ |
| 1056 | static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 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,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; |
| 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); | 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 | } | ||
| 1139 | 1155 | ||
| 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 @@ | ||
| 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 | } | ||