support foo.* for ptr deref

See #770
This commit is contained in:
Andrew Kelley 2018-04-30 14:20:56 -04:00
parent e14db23661
commit 76ab1d2b6c
8 changed files with 69 additions and 10 deletions

View File

@ -5958,10 +5958,12 @@ MultiplyOperator = "||" | "*" | "/" | "%" | "**" | "*%"
PrefixOpExpression = PrefixOp TypeExpr | SuffixOpExpression
SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | PtrDerefExpression)
FieldAccessExpression = "." Symbol
PtrDerefExpression = ".*"
FnCallExpression = "(" list(Expression, ",") ")"
ArrayAccessExpression = "[" Expression "]"
@ -5974,7 +5976,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")
StructLiteralField = "." Symbol "=" Expression
PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
PrefixOp = "!" | "-" | "~" | ("*" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType

View File

@ -379,6 +379,7 @@ enum NodeType {
NodeTypeArrayAccessExpr,
NodeTypeSliceExpr,
NodeTypeFieldAccessExpr,
NodeTypePtrDeref,
NodeTypeUse,
NodeTypeBoolLiteral,
NodeTypeNullLiteral,
@ -603,6 +604,10 @@ struct AstNodeFieldAccessExpr {
Buf *field_name;
};
struct AstNodePtrDerefExpr {
AstNode *target;
};
enum PrefixOp {
PrefixOpInvalid,
PrefixOpBoolNot,
@ -911,6 +916,7 @@ struct AstNode {
AstNodeCompTime comptime_expr;
AstNodeAsmExpr asm_expr;
AstNodeFieldAccessExpr field_access_expr;
AstNodePtrDerefExpr ptr_deref_expr;
AstNodeContainerDecl container_decl;
AstNodeStructField struct_field;
AstNodeStringLiteral string_literal;

View File

@ -3275,6 +3275,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeUnreachable:
case NodeTypeAsmExpr:
case NodeTypeFieldAccessExpr:
case NodeTypePtrDeref:
case NodeTypeStructField:
case NodeTypeContainerInitExpr:
case NodeTypeStructValueField:

View File

@ -222,6 +222,8 @@ static const char *node_type_str(NodeType node_type) {
return "AsmExpr";
case NodeTypeFieldAccessExpr:
return "FieldAccessExpr";
case NodeTypePtrDeref:
return "PtrDerefExpr";
case NodeTypeContainerDecl:
return "ContainerDecl";
case NodeTypeStructField:
@ -696,6 +698,13 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
print_symbol(ar, rhs);
break;
}
case NodeTypePtrDeref:
{
AstNode *lhs = node->data.ptr_deref_expr.target;
render_node_ungrouped(ar, lhs);
fprintf(ar->f, ".*");
break;
}
case NodeTypeUndefinedLiteral:
fprintf(ar->f, "undefined");
break;

View File

@ -4548,8 +4548,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
}
static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) {
assert(node->type == NodeTypePrefixOpExpr);
AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
AstNode *expr_node;
if (node->type == NodeTypePrefixOpExpr) {
expr_node = node->data.prefix_op_expr.primary_expr;
} else if (node->type == NodeTypePtrDeref) {
expr_node = node->data.ptr_deref_expr.target;
} else {
zig_unreachable();
}
IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval);
if (value == irb->codegen->invalid_instruction)
@ -6527,6 +6533,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
return ir_build_load_ptr(irb, scope, node, ptr_instruction);
}
case NodeTypePtrDeref:
return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval);
case NodeTypeThisLiteral:
return ir_lval_wrap(irb, scope, ir_gen_this_literal(irb, scope, node), lval);
case NodeTypeBoolLiteral:

View File

@ -1046,11 +1046,12 @@ static AstNode *ast_parse_fn_proto_partial(ParseContext *pc, size_t *token_index
}
/*
SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | PtrDerefExpression | SliceExpression)
FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
ArrayAccessExpression : token(LBracket) Expression token(RBracket)
SliceExpression = "[" Expression ".." option(Expression) "]"
FieldAccessExpression : token(Dot) token(Symbol)
PtrDerefExpression = ".*"
StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression
*/
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,
} else if (first_token->id == TokenIdDot) {
*token_index += 1;
Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
Token *token = &pc->tokens->at(*token_index);
AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, first_token);
node->data.field_access_expr.struct_expr = primary_expr;
node->data.field_access_expr.field_name = token_buf(name_token);
if (token->id == TokenIdSymbol) {
*token_index += 1;
AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, first_token);
node->data.field_access_expr.struct_expr = primary_expr;
node->data.field_access_expr.field_name = token_buf(token);
primary_expr = node;
} else if (token->id == TokenIdStar) {
*token_index += 1;
AstNode *node = ast_create_node(pc, NodeTypePtrDeref, first_token);
node->data.ptr_deref_expr.target = primary_expr;
primary_expr = node;
} else {
ast_invalid_token_error(pc, token);
}
primary_expr = node;
} else {
return primary_expr;
}
@ -3012,6 +3027,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
case NodeTypeFieldAccessExpr:
visit_field(&node->data.field_access_expr.struct_expr, visit, context);
break;
case NodeTypePtrDeref:
visit_field(&node->data.ptr_deref_expr.target, visit, context);
break;
case NodeTypeUse:
visit_field(&node->data.use.expr, visit, context);
break;

View File

@ -33,6 +33,7 @@ comptime {
_ = @import("cases/misc.zig");
_ = @import("cases/namespace_depends_on_compile_var/index.zig");
_ = @import("cases/null.zig");
_ = @import("cases/pointers.zig");
_ = @import("cases/pub_enum/index.zig");
_ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
_ = @import("cases/reflection.zig");

14
test/cases/pointers.zig Normal file
View File

@ -0,0 +1,14 @@
const std = @import("std");
const assert = std.debug.assert;
test "dereference pointer" {
comptime testDerefPtr();
testDerefPtr();
}
fn testDerefPtr() void {
var x: i32 = 1234;
var y = &x;
y.* += 1;
assert(x == 1235);
}