std: mem.Arena 를 구현한다
SPEC R11 은 재귀·그래프 모양 데이터를 아레나가 값을 소유하고 정수 핸들이
가리키는 것으로 답한다. 그 답은 아레나가 실제로 있어야 쓸 수 있다.
핸들은 오프셋이라 아레나가 사는 동안 유효하고, 두 핸들을 비교하는 것은 두 수를
비교하는 것이다. 아레나는 몰래 자라지 않는다 -- 움직인 핸들은 더 이상 아무것도
가리키지 않기 때문이다.
길에서 고친 것 셋:
- Self 가 제네릭 인스턴스에서만 타입으로 묶여 있어서, 평범한 구조체의 Self{..}
가 안 풀렸다. 이제 모든 메서드에서 묶는다.
- binding.Type.method() 가 식 자리에서 해석되지 않았다.
- 다른 유닛의 비제네릭 구조체 메서드가 lowering 되지 않고 extern 으로만 나갔다.
파일을 나눌 때 그 가지가 빠졌다.
handles 0 4 8 / value 65 / full / reset 0 / balanced
exec.py 26/26.
This commit is contained in:
@@ -358,6 +358,16 @@ FeType *type_from_expr(FeCheckerState *s, FeNode *n, int *ok)
|
||||
if (t && t->kind!=FE_TYPE_UNKNOWN) { *ok=1; return t; }
|
||||
return unknown(c);
|
||||
}
|
||||
/* `binding.Name` names a type in another unit. */
|
||||
if (n->kind==FE_N_MEMBER && n->a && n->a->kind==FE_N_IDENT &&
|
||||
n->b && n->b->text) {
|
||||
FeUnit *bound=binding_unit(s,n->a);
|
||||
if (bound) {
|
||||
FeType *there=unit_type(c,bound,n->b->text);
|
||||
if (there) { *ok=1; return there; }
|
||||
}
|
||||
return unknown(c);
|
||||
}
|
||||
if (n->kind==FE_N_CALL && n->a &&
|
||||
(n->a->kind==FE_N_IDENT ||
|
||||
(n->a->kind==FE_N_MEMBER && n->a->a &&
|
||||
|
||||
@@ -504,6 +504,16 @@ void check_method(FeCheck *c, FeNode *fn, FeScope *globals,
|
||||
FeCheckerState s;
|
||||
FeNode *x;
|
||||
FeType *t;
|
||||
FeBindSave self_save;
|
||||
/* `Self` names the type a method belongs to, wherever it appears -- in a
|
||||
signature, and in `Self{ .. }`. Binding it as a type makes both work the
|
||||
same way, and the same way a generic instance already worked. */
|
||||
self_save.count=c->types.param_count;
|
||||
{
|
||||
unsigned i;
|
||||
for(i=0;i<FE_TYPE_PARAM_MAX;++i) self_save.params[i]=c->types.params[i];
|
||||
}
|
||||
bind_self(c,owner);
|
||||
s.c=c;
|
||||
s.globals=globals;
|
||||
s.scope=scope_new(&s,globals);
|
||||
@@ -521,6 +531,7 @@ void check_method(FeCheck *c, FeNode *fn, FeScope *globals,
|
||||
local_cname(c,x->text ? x->text : "arg"),x);
|
||||
}
|
||||
if(fn->c) check_stmt(&s,fn->c);
|
||||
pop_bindings(c,&self_save);
|
||||
}
|
||||
|
||||
int m7_actual_compatible(FeType *want, FeType *got, FeNode *value)
|
||||
|
||||
@@ -98,6 +98,7 @@ int lower_reserve(Lower *L, void **items, unsigned *capacity, unsigned needed,
|
||||
|
||||
/* Every definition in lowering, so the split files can see each other. */
|
||||
FeIrType tag_type_of(const FeType *t);
|
||||
int struct_is_generic(const FeNode *decl);
|
||||
void lower_if_let(Lower *L, FeNode *n);
|
||||
unsigned wrapper_tag(Lower *L, Slot w, const FeType *t, FeNode *n);
|
||||
void bind_payload(Lower *L, Slot subject, const FeType *t,
|
||||
|
||||
@@ -515,6 +515,12 @@ void lower_global(Lower *L, FeNode *n)
|
||||
fe_ir_global(L->m, n->cname, ir_type(t), size, ir_align(t), init);
|
||||
}
|
||||
|
||||
/* A declaration with type parameters is a pattern, not code. */
|
||||
int struct_is_generic(const FeNode *decl)
|
||||
{
|
||||
return decl && decl->a && decl->a->children != 0;
|
||||
}
|
||||
|
||||
int fn_is_generic(const FeNode *fn)
|
||||
{
|
||||
FeNode *p;
|
||||
@@ -594,6 +600,13 @@ int fe_lower_program(FeCheck *c, FeIrModule *out)
|
||||
for (n = unit->ast.root ? unit->ast.root->children : 0; n; n = n->next)
|
||||
if (n->kind == FE_N_GLOBAL || n->kind == FE_N_CONST)
|
||||
lower_global(&L, n);
|
||||
else if (n->kind == FE_N_STRUCT && !struct_is_generic(n)) {
|
||||
/* A method is a function whose first parameter is the value it
|
||||
was reached through; the storage is the same either way. */
|
||||
FeNode *m;
|
||||
for (m = n->children; m; m = m->next)
|
||||
if (m->kind == FE_N_FN && m->c) lower_fn(&L, m);
|
||||
}
|
||||
else if (n->kind == FE_N_FN && !n->c) {
|
||||
/* A declaration with no body is something the linker will
|
||||
find: the runtime, or a C library. */
|
||||
|
||||
Reference in New Issue
Block a user