bool flatten_arrows(ast_t** astp, bool errors) { ast_t* ast = *astp; ast_t* node_type = ast_type(ast); if(node_type != NULL) { if(!flatten_arrows(&node_type, errors)) return false; } if(ast_id(ast) == TK_ARROW) { AST_GET_CHILDREN(ast, left, right); ast_t* flat; if(!flatten_arrows(&right, errors)) return false; if((ast_id(left) == TK_BOXTYPE) && (ast_id(right) != TK_ARROW)) flat = viewpoint_cap(TK_BOX, TK_NONE, right); else flat = viewpoint_type(left, right); if(flat == NULL) { if(errors) ast_error(ast, "can't flatten arrow type"); return false; } ast_replace(astp, flat); return true; } ast_t* child = ast_child(ast); while(child != NULL) { if(!flatten_arrows(&child, errors)) return false; child = ast_sibling(child); } return true; }
static ast_t* lookup_nominal(typecheck_t* t, ast_t* from, ast_t* orig, ast_t* type, const char* name, bool errors) { assert(ast_id(type) == TK_NOMINAL); ast_t* def = (ast_t*)ast_data(type); ast_t* type_name = ast_child(def); ast_t* find = ast_get(def, name, NULL); if(find != NULL) { switch(ast_id(find)) { case TK_FVAR: case TK_FLET: case TK_NEW: case TK_BE: case TK_FUN: break; default: find = NULL; } } if(find == NULL) { if(errors) ast_error(from, "couldn't find '%s' in '%s'", name, ast_name(type_name)); return NULL; } if((name[0] == '_') && (from != NULL) && (t != NULL)) { switch(ast_id(find)) { case TK_FVAR: case TK_FLET: if(t->frame->type != def) { if(errors) { ast_error(from, "can't lookup private fields from outside the type"); } return NULL; } break; case TK_NEW: case TK_BE: case TK_FUN: { if(ast_nearest(def, TK_PACKAGE) != t->frame->package) { if(errors) { ast_error(from, "can't lookup private methods from outside the package"); } return NULL; } break; } default: assert(0); return NULL; } if(!strcmp(name, "_final")) { switch(ast_id(find)) { case TK_NEW: case TK_BE: case TK_FUN: if(errors) ast_error(from, "can't lookup a _final function"); return NULL; default: {} } } } ast_t* typeparams = ast_sibling(type_name); ast_t* typeargs = ast_childidx(type, 2); find = ast_dup(find); orig = ast_dup(orig); replace_thistype(&find, orig); ast_free_unattached(orig); ast_t* r_find = reify(from, find, typeparams, typeargs); if(r_find != find) { ast_free_unattached(find); find = r_find; } if((find != NULL) && !flatten_arrows(&find, errors)) { if(errors) ast_error(from, "can't look this up on a tag"); ast_free_unattached(find); return NULL; } return find; }