mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 22:33:08 +00:00
support addressof operator and struct pointer field access
This commit is contained in:
parent
5a8822c714
commit
aa56f016f7
@ -11,6 +11,13 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
|||||||
|
|
||||||
test_foo(foo);
|
test_foo(foo);
|
||||||
|
|
||||||
|
modify_foo(&foo);
|
||||||
|
|
||||||
|
if foo.c != 100 {
|
||||||
|
print_str("BAD\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
print_str("OK\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,7 +28,11 @@ struct Foo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn test_foo(foo : Foo) {
|
fn test_foo(foo : Foo) {
|
||||||
if foo.b {
|
if !foo.b {
|
||||||
print_str("OK\n" as string);
|
print_str("BAD\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn modify_foo(foo : &Foo) {
|
||||||
|
foo.c = 100;
|
||||||
|
}
|
||||||
|
|||||||
@ -116,6 +116,9 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
|
|||||||
entry->align_in_bits = g->pointer_size_bytes * 8;
|
entry->align_in_bits = g->pointer_size_bytes * 8;
|
||||||
entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type,
|
entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type,
|
||||||
entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name));
|
entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name));
|
||||||
|
entry->data.pointer.child_type = child_type;
|
||||||
|
entry->data.pointer.is_const = is_const;
|
||||||
|
|
||||||
g->type_table.put(&entry->name, entry);
|
g->type_table.put(&entry->name, entry);
|
||||||
*parent_pointer = entry;
|
*parent_pointer = entry;
|
||||||
return entry;
|
return entry;
|
||||||
@ -575,6 +578,10 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type,
|
|||||||
case TypeTableEntryIdFloat:
|
case TypeTableEntryIdFloat:
|
||||||
if (is_num_lit_float(num_lit)) {
|
if (is_num_lit_float(num_lit)) {
|
||||||
return lit_size_in_bits <= other_type->size_in_bits;
|
return lit_size_in_bits <= other_type->size_in_bits;
|
||||||
|
} else if (other_type->size_in_bits == 32) {
|
||||||
|
return lit_size_in_bits < 24;
|
||||||
|
} else if (other_type->size_in_bits == 64) {
|
||||||
|
return lit_size_in_bits < 53;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -810,14 +817,19 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
|
|||||||
|
|
||||||
TypeTableEntry *return_type;
|
TypeTableEntry *return_type;
|
||||||
|
|
||||||
if (struct_type->id == TypeTableEntryIdStruct) {
|
if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
|
||||||
|
struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
|
||||||
|
{
|
||||||
assert(node->codegen_node);
|
assert(node->codegen_node);
|
||||||
FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node;
|
FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node;
|
||||||
assert(codegen_field_access);
|
assert(codegen_field_access);
|
||||||
|
|
||||||
Buf *field_name = &node->data.field_access_expr.field_name;
|
Buf *field_name = &node->data.field_access_expr.field_name;
|
||||||
|
|
||||||
get_struct_field(struct_type, field_name,
|
TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ?
|
||||||
|
struct_type : struct_type->data.pointer.child_type;
|
||||||
|
|
||||||
|
get_struct_field(bare_struct_type, field_name,
|
||||||
&codegen_field_access->type_struct_field,
|
&codegen_field_access->type_struct_field,
|
||||||
&codegen_field_access->field_index);
|
&codegen_field_access->field_index);
|
||||||
if (codegen_field_access->type_struct_field) {
|
if (codegen_field_access->type_struct_field) {
|
||||||
|
|||||||
@ -20,8 +20,8 @@ struct VariableTableEntry;
|
|||||||
struct CastNode;
|
struct CastNode;
|
||||||
|
|
||||||
struct TypeTableEntryPointer {
|
struct TypeTableEntryPointer {
|
||||||
TypeTableEntry *pointer_child;
|
TypeTableEntry *child_type;
|
||||||
bool pointer_is_const;
|
bool is_const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TypeTableEntryInt {
|
struct TypeTableEntryInt {
|
||||||
|
|||||||
@ -248,6 +248,8 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node) {
|
|||||||
TypeTableEntry *type_entry;
|
TypeTableEntry *type_entry;
|
||||||
LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry);
|
LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry);
|
||||||
return LLVMBuildLoad(g->builder, ptr, "");
|
return LLVMBuildLoad(g->builder, ptr, "");
|
||||||
|
} else if (struct_type->id == TypeTableEntryIdPointer) {
|
||||||
|
zig_panic("TODO struct pointer access");
|
||||||
} else {
|
} else {
|
||||||
zig_panic("gen_field_access_expr bad struct type");
|
zig_panic("gen_field_access_expr bad struct type");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1153,12 +1153,13 @@ static PrefixOp tok_to_prefix_op(Token *token) {
|
|||||||
case TokenIdBang: return PrefixOpBoolNot;
|
case TokenIdBang: return PrefixOpBoolNot;
|
||||||
case TokenIdDash: return PrefixOpNegation;
|
case TokenIdDash: return PrefixOpNegation;
|
||||||
case TokenIdTilde: return PrefixOpBinNot;
|
case TokenIdTilde: return PrefixOpBinNot;
|
||||||
|
case TokenIdAmpersand: return PrefixOpAddressOf;
|
||||||
default: return PrefixOpInvalid;
|
default: return PrefixOpInvalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
PrefixOp : token(Not) | token(Dash) | token(Tilde)
|
PrefixOp : token(Not) | token(Dash) | token(Tilde) | (token(Ampersand) option(token(Const)))
|
||||||
*/
|
*/
|
||||||
static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool mandatory) {
|
static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool mandatory) {
|
||||||
Token *token = &pc->tokens->at(*token_index);
|
Token *token = &pc->tokens->at(*token_index);
|
||||||
@ -1171,6 +1172,15 @@ static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool man
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*token_index += 1;
|
*token_index += 1;
|
||||||
|
|
||||||
|
if (result == PrefixOpAddressOf) {
|
||||||
|
Token *token = &pc->tokens->at(*token_index);
|
||||||
|
if (token->id == TokenIdKeywordConst) {
|
||||||
|
*token_index += 1;
|
||||||
|
result = PrefixOpConstAddressOf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -569,6 +569,11 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
|||||||
foo.a += 1;
|
foo.a += 1;
|
||||||
foo.b = foo.a == 1;
|
foo.b = foo.a == 1;
|
||||||
test_foo(foo);
|
test_foo(foo);
|
||||||
|
test_mutation(&foo);
|
||||||
|
if foo.c != 100 {
|
||||||
|
print_str("BAD\n");
|
||||||
|
}
|
||||||
|
print_str("OK\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
struct Foo {
|
struct Foo {
|
||||||
@ -577,9 +582,12 @@ struct Foo {
|
|||||||
c : f32,
|
c : f32,
|
||||||
}
|
}
|
||||||
fn test_foo(foo : Foo) {
|
fn test_foo(foo : Foo) {
|
||||||
if foo.b {
|
if !foo.b {
|
||||||
print_str("OK\n");
|
print_str("BAD\n");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
fn test_mutation(foo : &Foo) {
|
||||||
|
foo.c = 100;
|
||||||
}
|
}
|
||||||
)SOURCE", "OK\n");
|
)SOURCE", "OK\n");
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user