std: map 을 쓴다 -- 바이트 열에서 값으로
컴파일러는 이름을 끊임없이 찾는데 리스트 선형 탐색은 그 모양이 아니다. 키는 맵이 소유하는 한 버퍼에 복사되고 슬롯은 그 안의 어디인지만 적는다 -- R11 이 말하는 아레나와 핸들 모양이고, 그래서 맵을 놓는 것이 엔트리마다 하나가 아니라 두 번의 해제다. 개방 주소법에 선형 탐사. 표는 2의 거듭제곱이라 나눗셈이 아니라 마스크이고, 탐사가 길어지는 것이 표가 차는 것보다 먼저라 3/4 에서 자란다. 길에서 고친 것 넷: - 인스턴스를 만들 때 선언 유닛으로 전환하지 않아서, 필드 타입 Slot(V) 를 호출자 유닛에서 찾고 있었다. - mem.alloc_slice 가 원소 타입으로 단순한 이름만 받았다. Slot(V) 같은 인스턴스도 받는다. - 쓸 수 있는지를 바인딩이 아니라 소유된 것이 정한다. let p: ^[]mut T 는 p 를 고정하고 그것이 소유한 것은 쓸 수 있게 둔다. 슬라이스 인덱스도 마찬가지다. - 메서드 인자에 자유 함수와 같은 호출 한정 약화가 없었다. 알게 된 것: 대여는 루트 단위라 self 의 한 필드에 쓰는 동안 다른 필드를 읽을 수 없다. 지역으로 빼거나 메서드를 나누면 되지만, 필드 단위 대여가 있으면 훨씬 편할 자리다. count 5 / fn 2 let 3 missing 0 / grown 64 / after 40 / balanced 218/218, 28/28.
This commit is contained in:
+38
-7
@@ -142,9 +142,20 @@ int lvalue_writable(FeCheckerState *s, FeNode *n)
|
||||
t=n->a ? n->a->sem_type : 0;
|
||||
if (t && t->kind==FE_TYPE_REF && n->b && n->b->text &&
|
||||
strcmp(n->b->text,"^")==0) return t->ref_mut;
|
||||
/* Through an owner, what may be written is decided by what is owned,
|
||||
not by whether the binding may be pointed somewhere else. `let p:
|
||||
^[]mut T` fixes p and leaves what it owns writable. */
|
||||
if (t && t->kind==FE_TYPE_OWNED && n->b && n->b->text &&
|
||||
strcmp(n->b->text,"^")==0)
|
||||
return !t->elem || t->elem->kind!=FE_TYPE_SLICE || t->elem->ref_mut;
|
||||
return lvalue_writable(s,n->a);
|
||||
}
|
||||
if (n->kind == FE_N_INDEX) {
|
||||
/* An index into a slice asks the slice, not the binding. */
|
||||
t=n->a ? n->a->sem_type : 0;
|
||||
if (t && t->kind==FE_TYPE_SLICE) return t->ref_mut;
|
||||
return lvalue_writable(s,n->a);
|
||||
}
|
||||
if (n->kind == FE_N_INDEX) return lvalue_writable(s,n->a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -440,10 +451,16 @@ FeType *check_expr_core(FeCheckerState *s, FeNode *n)
|
||||
if (strcmp(n->a->b->text,"alloc_slice")==0) {
|
||||
FeNode *count=arg ? arg->next : 0;
|
||||
FeType *item;
|
||||
if(!arg || arg->kind!=FE_N_IDENT || !count || count->next)
|
||||
err(c,n->loc,"mem.alloc_slice requires a type and length");
|
||||
item=arg && arg->kind==FE_N_IDENT ?
|
||||
fe_type_intern(&c->types,arg->text) : unknown(c);
|
||||
{
|
||||
/* The element type may be an instance -- `Slot(V)` -- and
|
||||
not just a name. */
|
||||
int named=0;
|
||||
item=arg ? type_from_expr(s,arg,&named) : unknown(c);
|
||||
if(!arg || !named || !count || count->next) {
|
||||
err(c,n->loc,"mem.alloc_slice requires a type and length");
|
||||
item=unknown(c);
|
||||
}
|
||||
}
|
||||
b=count ? check_expr(s,count) : unknown(c);
|
||||
if(known(b) && !fe_type_is_integer(b))
|
||||
err(c,count->loc,"slice length must be an integer");
|
||||
@@ -578,9 +595,23 @@ FeType *check_expr_core(FeCheckerState *s, FeNode *n)
|
||||
while(param && arg) {
|
||||
a=check_expr(s,arg);
|
||||
b=method_type(c,param->a,et);
|
||||
if(!compatible(b,a,arg) && a->kind!=FE_TYPE_UNKNOWN)
|
||||
/* A method argument gets the same call-only weakening a
|
||||
free function's does: an exclusive view may be handed
|
||||
over as a shared one for the length of the call, and an
|
||||
exclusive borrow is lent rather than given. */
|
||||
if(!compatible(b,a,arg) &&
|
||||
!(b && a && b->kind==FE_TYPE_SLICE &&
|
||||
a->kind==FE_TYPE_SLICE && !b->ref_mut && a->ref_mut &&
|
||||
fe_type_equal(b->elem,a->elem)) &&
|
||||
!(b && a && b->kind==FE_TYPE_REF && a->kind==FE_TYPE_REF &&
|
||||
!b->ref_mut && a->ref_mut &&
|
||||
fe_type_equal(b->elem,a->elem)) &&
|
||||
a->kind!=FE_TYPE_UNKNOWN)
|
||||
err(c,arg->loc,"method argument type mismatch");
|
||||
mark_moved(s,arg,a);
|
||||
if(!call_reborrows(b,a) &&
|
||||
!(b && a && b->kind==FE_TYPE_SLICE &&
|
||||
a->kind==FE_TYPE_SLICE && !b->ref_mut && a->ref_mut))
|
||||
mark_moved(s,arg,a);
|
||||
param=param->next;
|
||||
arg=arg->next;
|
||||
}
|
||||
|
||||
@@ -226,9 +226,13 @@ FeType *build_struct_instance(FeCheck *c, FeUnit *home, FeNode *decl,
|
||||
for (f=decl->children;f;f=f->next) if (f->kind==FE_N_FIELD) ++fields;
|
||||
t->field_count=fields;
|
||||
if (fields) {
|
||||
const char *save_unit=c->types.unit_name;
|
||||
t->fields=(FeFieldType *)fe_arena_alloc(&c->arena,
|
||||
fields*sizeof(FeFieldType));
|
||||
if (!t->fields) { t->field_count=0; return t; }
|
||||
/* Field types are written in the unit that declared the struct, not in
|
||||
whichever unit asked for this instance. */
|
||||
c->types.unit_name=home->name;
|
||||
push_instance_bindings(c,&save,t);
|
||||
bind_self(c,t);
|
||||
i=0;
|
||||
@@ -240,6 +244,7 @@ FeType *build_struct_instance(FeCheck *c, FeUnit *home, FeNode *decl,
|
||||
++i;
|
||||
}
|
||||
pop_bindings(c,&save);
|
||||
c->types.unit_name=save_unit;
|
||||
}
|
||||
fe_type_layout_all(&c->types);
|
||||
/* A type that says how to let go of itself needs that method to exist for
|
||||
|
||||
Reference in New Issue
Block a user