aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-02-19 12:47:02 +0000
committerGinger Bill <bill@gingerbill.org>2017-02-19 12:47:02 +0000
commitc0d5237b75b1ce19ee0e003dcd2dcffa66c442fd (patch)
treed1e4469d9c0248944be388f85bc2df0b914a0008
parent6fdcbefe5d488deea2825d908ff36af624e170d2 (diff)
Unexported struct fields on selectors
-rw-r--r--code/demo.odin7
-rw-r--r--core/fmt.odin2
-rw-r--r--src/check_expr.c48
3 files changed, 39 insertions, 18 deletions
diff --git a/code/demo.odin b/code/demo.odin
index dc93ab9e9..5b1c82522 100644
--- a/code/demo.odin
+++ b/code/demo.odin
@@ -8,6 +8,13 @@
#import "halloc.odin";
main :: proc() {
+ m: map[int]int;
+ m[123] = 312;
+ fmt.println(m[123]);
+ delete(m, 123);
+ fmt.println(m[123]);
+
+
/*
/*
Version 0.1.1
diff --git a/core/fmt.odin b/core/fmt.odin
index 6e0856ecb..d340bbe5d 100644
--- a/core/fmt.odin
+++ b/core/fmt.odin
@@ -11,8 +11,6 @@ Buffer :: struct {
length: int,
}
-
-
buffer_write :: proc(buf: ^Buffer, b: []byte) {
if buf.length < buf.data.count {
n := min(buf.data.count-buf.length, b.count);
diff --git a/src/check_expr.c b/src/check_expr.c
index a36838f97..4c1deb265 100644
--- a/src/check_expr.c
+++ b/src/check_expr.c
@@ -2576,6 +2576,27 @@ isize entity_overload_count(Scope *s, String name) {
return 1;
}
+bool check_is_field_exported(Checker *c, Entity *field) {
+ if (field == NULL) {
+ // NOTE(bill): Just incase
+ return true;
+ }
+ if (field->kind != Entity_Variable) {
+ return true;
+ }
+ Scope *file_scope = field->scope;
+ if (file_scope == NULL) {
+ return true;
+ }
+ while (!file_scope->is_file) {
+ file_scope = file_scope->parent;
+ }
+ if (!is_entity_exported(field) && file_scope != c->context.file_scope) {
+ return false;
+ }
+ return true;
+}
+
Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_hint) {
ast_node(se, SelectorExpr, node);
@@ -2701,7 +2722,13 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
if (entity == NULL && selector->kind == AstNode_Ident) {
- sel = lookup_field(c->allocator, operand->type, selector->Ident.string, operand->mode == Addressing_Type);
+ String field_name = selector->Ident.string;
+ sel = lookup_field(c->allocator, operand->type, field_name, operand->mode == Addressing_Type);
+
+ if (operand->mode != Addressing_Type && !check_is_field_exported(c, sel.entity)) {
+ error_node(op_expr, "`%.*s` is an unexported field", LIT(field_name));
+ goto error;
+ }
entity = sel.entity;
// NOTE(bill): Add type info needed for fields like `names`
@@ -4470,16 +4497,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
error_node(elem, "Unknown field `%.*s` in structure literal", LIT(name));
continue;
}
- if (!is_unknown) {
- Entity *f = sel.entity;
- Scope *file_scope = f->scope;
- while (!file_scope->is_file) {
- file_scope = file_scope->parent;
- }
- if (!is_entity_exported(f) && file_scope != c->context.file_scope) {
- error_node(elem, "Cannot assign to an unexported field `%.*s` in structure literal", LIT(name));
- continue;
- }
+ if (!is_unknown && !check_is_field_exported(c, sel.entity)) {
+ error_node(elem, "Cannot assign to an unexported field `%.*s` in structure literal", LIT(name));
+ continue;
}
@@ -4524,11 +4544,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
break;
}
- Scope *file_scope = field->scope;
- while (!file_scope->is_file) {
- file_scope = file_scope->parent;
- }
- if (!is_entity_exported(field) && file_scope != c->context.file_scope) {
+ if (!check_is_field_exported(c, field)) {
gbString t = type_to_string(type);
error_node(o->expr, "Implicit assignment to an unexported field `%.*s` in `%s` literal",
LIT(field->token.string), t);