support addressof operator and struct pointer field access
parent
5a8822c714
commit
aa56f016f7
|
@ -11,6 +11,13 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
|||
|
||||
test_foo(foo);
|
||||
|
||||
modify_foo(&foo);
|
||||
|
||||
if foo.c != 100 {
|
||||
print_str("BAD\n");
|
||||
}
|
||||
|
||||
print_str("OK\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -21,7 +28,11 @@ struct Foo {
|
|||
}
|
||||
|
||||
fn test_foo(foo : Foo) {
|
||||
if foo.b {
|
||||
print_str("OK\n" as string);
|
||||
if !foo.b {
|
||||
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->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type,
|
||||
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);
|
||||
*parent_pointer = entry;
|
||||
return entry;
|
||||
|
@ -575,6 +578,10 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type,
|
|||
case TypeTableEntryIdFloat:
|
||||
if (is_num_lit_float(num_lit)) {
|
||||
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 {
|
||||
return false;
|
||||
}
|
||||
|
@ -810,14 +817,19 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
|
|||
|
||||
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);
|
||||
FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node;
|
||||
assert(codegen_field_access);
|
||||
|
||||
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->field_index);
|
||||
if (codegen_field_access->type_struct_field) {
|
||||
|
|
|
@ -20,8 +20,8 @@ struct VariableTableEntry;
|
|||
struct CastNode;
|
||||
|
||||
struct TypeTableEntryPointer {
|
||||
TypeTableEntry *pointer_child;
|
||||
bool pointer_is_const;
|
||||
TypeTableEntry *child_type;
|
||||
bool is_const;
|
||||
};
|
||||
|
||||
struct TypeTableEntryInt {
|
||||
|
|
|
@ -248,6 +248,8 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node) {
|
|||
TypeTableEntry *type_entry;
|
||||
LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry);
|
||||
return LLVMBuildLoad(g->builder, ptr, "");
|
||||
} else if (struct_type->id == TypeTableEntryIdPointer) {
|
||||
zig_panic("TODO struct pointer access");
|
||||
} else {
|
||||
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 TokenIdDash: return PrefixOpNegation;
|
||||
case TokenIdTilde: return PrefixOpBinNot;
|
||||
case TokenIdAmpersand: return PrefixOpAddressOf;
|
||||
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) {
|
||||
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;
|
||||
|
||||
if (result == PrefixOpAddressOf) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id == TokenIdKeywordConst) {
|
||||
*token_index += 1;
|
||||
result = PrefixOpConstAddressOf;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -569,6 +569,11 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
|||
foo.a += 1;
|
||||
foo.b = foo.a == 1;
|
||||
test_foo(foo);
|
||||
test_mutation(&foo);
|
||||
if foo.c != 100 {
|
||||
print_str("BAD\n");
|
||||
}
|
||||
print_str("OK\n");
|
||||
return 0;
|
||||
}
|
||||
struct Foo {
|
||||
|
@ -577,9 +582,12 @@ struct Foo {
|
|||
c : f32,
|
||||
}
|
||||
fn test_foo(foo : Foo) {
|
||||
if foo.b {
|
||||
print_str("OK\n");
|
||||
if !foo.b {
|
||||
print_str("BAD\n");
|
||||
}
|
||||
}
|
||||
fn test_mutation(foo : &Foo) {
|
||||
foo.c = 100;
|
||||
}
|
||||
)SOURCE", "OK\n");
|
||||
|
||||
|
|
Loading…
Reference in New Issue