bh_arr(AstBlock *) block_stack = NULL;
static b32 report_unresolved_symbols = 1;
-AstType* symres_type(AstType* type);
+#define SYMRES(kind, ...) do { \
+ SymresStatus ss = symres_ ## kind (__VA_ARGS__); \
+ if (ss > Symres_Errors_Start) return ss; \
+ } while (0)
+
+typedef enum SymresStatus {
+ Symres_Success,
+ Symres_Complete,
+
+ Symres_Errors_Start,
+ Symres_Yield,
+ Symres_Error,
+} SymresStatus;
+
+static void symres_type(AstType** type);
static void symres_local(AstLocal** local, b32 add_to_block_locals);
static void symres_call(AstCall* call);
static void symres_size_of(AstSizeOf* so);
}
}
-AstType* symres_type(AstType* type) {
- if (type == NULL) return NULL;
-
- if (type->kind == Ast_Kind_Type_Alias) {
- ((AstTypeAlias *) type)->to = symres_type(((AstTypeAlias *) type)->to);
- return type;
- }
+static void symres_struct_type(AstStructType* s_node) {
+ if (s_node->flags & Ast_Flag_Type_Is_Resolved) return;
- if (type->kind == Ast_Kind_Symbol) {
- symres_symbol((AstNode **) &type);
- return type;
- }
+ s_node->flags |= Ast_Flag_Type_Is_Resolved;
+
+ {
+ bh_table(i32) mem_set;
+ bh_table_init(global_heap_allocator, mem_set, bh_arr_length(s_node->members));
- if (type->kind == Ast_Kind_Field_Access) {
- AstFieldAccess* field = (AstFieldAccess *) type;
- symres_field_access(&field);
+ bh_arr_each(AstStructMember *, member, s_node->members) {
+ token_toggle_end((*member)->token);
- if (!node_is_type((AstNode *) field))
- onyx_report_error(type->token->pos, "field access did not result in a type");
+ if (bh_table_has(i32, mem_set, (*member)->token->text)) {
+ onyx_report_error((*member)->token->pos,
+ "Duplicate struct member '%s'.",
+ (*member)->token->text);
- return (AstType *) field;
- }
+ token_toggle_end((*member)->token);
+ return;
+ }
- // NOTE: Already resolved
- if (type->kind == Ast_Kind_Basic_Type) return type;
+ bh_table_put(i32, mem_set, (*member)->token->text, 1);
+ token_toggle_end((*member)->token);
+ }
- if (type->kind == Ast_Kind_Pointer_Type) {
- ((AstPointerType *) type)->elem = symres_type(((AstPointerType *) type)->elem);
- return type;
+ bh_table_free(mem_set);
}
- if (type->kind == Ast_Kind_Function_Type) {
- AstFunctionType* ftype = (AstFunctionType *) type;
-
- ftype->return_type = symres_type(ftype->return_type);
-
- if (ftype->param_count > 0)
- fori (i, 0, (i64) ftype->param_count) {
- ftype->params[i] = symres_type(ftype->params[i]);
- }
+ if (s_node->scope) {
+ // FIX: This is probably wrong for the long term.
+ s_node->scope->parent = curr_scope;
- return type;
+ scope_enter(s_node->scope);
}
- if (type->kind == Ast_Kind_Struct_Type) {
- AstStructType* s_node = (AstStructType *) type;
- if (s_node->flags & Ast_Flag_Type_Is_Resolved) return type;
+ fori (i, 0, bh_arr_length(s_node->members)) {
+ AstStructMember *member = s_node->members[i];
- s_node->flags |= Ast_Flag_Type_Is_Resolved;
-
- {
- bh_table(i32) mem_set;
- bh_table_init(global_heap_allocator, mem_set, bh_arr_length(s_node->members));
-
- bh_arr_each(AstStructMember *, member, s_node->members) {
- token_toggle_end((*member)->token);
-
- if (bh_table_has(i32, mem_set, (*member)->token->text)) {
- onyx_report_error((*member)->token->pos,
- "Duplicate struct member '%s'.",
- (*member)->token->text);
+ if (member->type_node) {
+ symres_type(&member->type_node);
- token_toggle_end((*member)->token);
- return type;
- }
-
- bh_table_put(i32, mem_set, (*member)->token->text, 1);
- token_toggle_end((*member)->token);
+ if (!node_is_type((AstNode *) member->type_node)) {
+ onyx_report_error(member->token->pos, "Member type is not a type.");
+ goto struct_symres_done;
}
- bh_table_free(mem_set);
- }
+ if (member->flags & Ast_Flag_Struct_Mem_Used) {
+ AstType *used = (AstType *) member->type_node;
- if (s_node->scope) {
- // FIX: This is probably wrong for the long term.
- s_node->scope->parent = curr_scope;
-
- scope_enter(s_node->scope);
- }
-
- fori (i, 0, bh_arr_length(s_node->members)) {
- AstStructMember *member = s_node->members[i];
-
- if (member->type_node) {
- member->type_node = symres_type(member->type_node);
-
- if (!node_is_type((AstNode *) member->type_node)) {
- onyx_report_error(member->token->pos, "Member type is not a type.");
- goto struct_symres_done;
+ while (used->kind == Ast_Kind_Type_Alias) {
+ used = ((AstTypeAlias *) used)->to;
}
- if (member->flags & Ast_Flag_Struct_Mem_Used) {
- AstType *used = (AstType *) member->type_node;
-
- while (used->kind == Ast_Kind_Type_Alias) {
- used = ((AstTypeAlias *) used)->to;
- }
+ b32 use_works = (used->kind == Ast_Kind_Struct_Type || used->kind == Ast_Kind_Poly_Call_Type);
- b32 use_works = (used->kind == Ast_Kind_Struct_Type || used->kind == Ast_Kind_Poly_Call_Type);
-
- if (used->kind == Ast_Kind_Type_Raw_Alias) {
- AstTypeRawAlias* alias = (AstTypeRawAlias *) used;
- use_works = (alias->to->kind == Type_Kind_Struct);
- }
+ if (used->kind == Ast_Kind_Type_Raw_Alias) {
+ AstTypeRawAlias* alias = (AstTypeRawAlias *) used;
+ use_works = (alias->to->kind == Type_Kind_Struct);
+ }
- if (!use_works) {
- onyx_report_error(member->token->pos,
- "Can only 'use' members of struct type, got '%s'.",
- onyx_ast_node_kind_string(used->kind));
- goto struct_symres_done;
- }
+ if (!use_works) {
+ onyx_report_error(member->token->pos,
+ "Can only 'use' members of struct type, got '%s'.",
+ onyx_ast_node_kind_string(used->kind));
+ goto struct_symres_done;
}
}
}
+ }
struct_symres_done:
- if (s_node->scope) scope_leave();
- return type;
- }
+ if (s_node->scope) scope_leave();
+}
- if (type->kind == Ast_Kind_Array_Type) {
- AstArrayType* a_node = (AstArrayType *) type;
+static void symres_type(AstType** type) {
+ if (!type || !*type) return;
- if (a_node->count_expr) symres_expression(&a_node->count_expr);
- a_node->elem = symres_type(a_node->elem);
+ switch ((*type)->kind) {
+ case Ast_Kind_Symbol: symres_symbol((AstNode **) type); break;
+ case Ast_Kind_Basic_Type: break;
+ case Ast_Kind_Type_Alias: symres_type(&((AstTypeAlias *) *type)->to); break;
+ case Ast_Kind_Field_Access: {
+ symres_field_access((AstFieldAccess **) type);
- return type;
- }
+ if (!node_is_type((AstNode *) *type))
+ onyx_report_error((*type)->token->pos, "Field access did not result in a type.");
+ break;
+ }
- if (type->kind == Ast_Kind_Enum_Type) {
- // symres_enum((AstEnumType *) type);
- return type;
- }
+ case Ast_Kind_Pointer_Type: symres_type(&((AstPointerType *) *type)->elem); break;
+ case Ast_Kind_Slice_Type: symres_type(&((AstSliceType *) *type)->elem); break;
+ case Ast_Kind_DynArr_Type: symres_type(&((AstDynArrType *) *type)->elem); break;
+ case Ast_Kind_VarArg_Type: symres_type(&((AstVarArgType *) *type)->elem); break;
- if (type->kind == Ast_Kind_Slice_Type) {
- AstSliceType* s_node = (AstSliceType *) type;
- s_node->elem = symres_type(s_node->elem);
+ case Ast_Kind_Function_Type: {
+ AstFunctionType* ftype = (AstFunctionType *) *type;
- return type;
- }
+ symres_type(&ftype->return_type);
- if (type->kind == Ast_Kind_DynArr_Type) {
- AstDynArrType* da_node = (AstDynArrType *) type;
- da_node->elem = symres_type(da_node->elem);
+ if (ftype->param_count > 0) {
+ fori (i, 0, (i64) ftype->param_count) {
+ symres_type(&ftype->params[i]);
+ }
+ }
+ break;
+ }
- return type;
- }
+ case Ast_Kind_Struct_Type: symres_struct_type((AstStructType *) *type); break;
+ case Ast_Kind_Array_Type: {
+ AstArrayType* a_node = (AstArrayType *) *type;
- if (type->kind == Ast_Kind_VarArg_Type) {
- AstVarArgType* va_node = (AstVarArgType *) type;
- va_node->elem = symres_type(va_node->elem);
+ if (a_node->count_expr) symres_expression(&a_node->count_expr);
+ symres_type(&a_node->elem);
+ break;
+ }
- return type;
- }
+ case Ast_Kind_Enum_Type: break;
- if (type->kind == Ast_Kind_Poly_Struct_Type) {
- AstPolyStructType* pst_node = (AstPolyStructType *) type;
- pst_node->scope = scope_create(context.ast_alloc, curr_scope, pst_node->token->pos);
+ case Ast_Kind_Poly_Struct_Type: {
+ AstPolyStructType* pst_node = (AstPolyStructType *) *type;
+ pst_node->scope = scope_create(context.ast_alloc, curr_scope, pst_node->token->pos);
- bh_arr_each(AstPolyStructParam, param, pst_node->poly_params) {
- param->type_node = symres_type(param->type_node);
- param->type = type_build_from_ast(context.ast_alloc, param->type_node);
+ bh_arr_each(AstPolyStructParam, param, pst_node->poly_params) {
+ symres_type(¶m->type_node);
+ param->type = type_build_from_ast(context.ast_alloc, param->type_node);
+ }
+ break;
}
- return type;
- }
-
- if (type->kind == Ast_Kind_Poly_Call_Type) {
- AstPolyCallType* pc_node = (AstPolyCallType *) type;
+ case Ast_Kind_Poly_Call_Type: {
+ AstPolyCallType* pc_node = (AstPolyCallType *) *type;
- pc_node->callee = symres_type(pc_node->callee);
+ symres_type(&pc_node->callee);
- bh_arr_each(AstNode *, param, pc_node->params) {
- if (node_is_type(*param)) {
- *param = (AstNode *) symres_type((AstType *) *param);
- } else {
- symres_expression((AstTyped **) param);
+ bh_arr_each(AstNode *, param, pc_node->params) {
+ if (node_is_type(*param)) {
+ symres_type((AstType **) param);
+ } else {
+ symres_expression((AstTyped **) param);
+ }
}
+ break;
}
- return type;
- }
-
- if (type->kind == Ast_Kind_Type_Compound) {
- AstCompoundType* ctype = (AstCompoundType *) type;
+ case Ast_Kind_Type_Compound: {
+ AstCompoundType* ctype = (AstCompoundType *) *type;
- bh_arr_each(AstType *, type, ctype->types) {
- *type = symres_type(*type);
+ bh_arr_each(AstType *, type, ctype->types) symres_type(type);
}
}
-
- return type;
}
static void symres_local(AstLocal** local, b32 add_to_block_locals) {
- (*local)->type_node = symres_type((*local)->type_node);
+ symres_type(&(*local)->type_node);
// NOTE: This is a little gross, but it is allows for finer control
// over when locals are in scope in a block, which reduces the number
}
static void symres_size_of(AstSizeOf* so) {
- so->type_node = symres_type(so->type_node);
- so->so_ast_type = symres_type(so->so_ast_type);
+ symres_type(&so->type_node);
+ symres_type(&so->so_ast_type);
}
static void symres_align_of(AstAlignOf* ao) {
- ao->type_node = symres_type(ao->type_node);
- ao->ao_ast_type = symres_type(ao->ao_ast_type);
+ symres_type(&ao->type_node);
+ symres_type(&ao->ao_ast_type);
}
static void symres_field_access(AstFieldAccess** fa) {
static void symres_unaryop(AstUnaryOp** unaryop) {
if ((*unaryop)->operation == Unary_Op_Cast) {
- (*unaryop)->type_node = symres_type((*unaryop)->type_node);
+ symres_type(&(*unaryop)->type_node);
}
symres_expression(&(*unaryop)->expr);
static void symres_struct_literal(AstStructLiteral* sl) {
if (sl->stnode != NULL) symres_expression(&sl->stnode);
- sl->stnode = (AstTyped *) symres_type((AstType *) sl->stnode);
+ symres_type((AstType **) &sl->stnode);
if (sl->stnode == NULL || sl->stnode->kind == Ast_Kind_Error || sl->stnode->kind == Ast_Kind_Symbol) return;
sl->type_node = (AstType *) sl->stnode;
static void symres_array_literal(AstArrayLiteral* al) {
if (al->atnode != NULL) symres_expression(&al->atnode);
- al->atnode = (AstTyped *) symres_type((AstType *) al->atnode);
+ symres_type((AstType **) &al->atnode);
if (al->atnode == NULL || al->atnode->kind == Ast_Kind_Error || al->atnode->kind == Ast_Kind_Symbol) return;
al->type_node = (AstType *) al->atnode;
static void symres_expression(AstTyped** expr) {
if (node_is_type((AstNode *) *expr)) {
- *((AstType **) expr) = symres_type((AstType *) *expr);
+ symres_type((AstType **) expr);
return;
}
symres_expression(&((AstRangeLiteral *)(*expr))->low);
symres_expression(&((AstRangeLiteral *)(*expr))->high);
- (*expr)->type_node = symres_type(builtin_range_type);
+ symres_type(&builtin_range_type);
+ (*expr)->type_node = builtin_range_type;
// NOTE: This is a weird place to put this so maybe put it somewhere else eventually
// - brendanfh 2020/09/04
case Ast_Kind_Function:
case Ast_Kind_NumLit:
- (*expr)->type_node = symres_type((*expr)->type_node);
+ symres_type(&(*expr)->type_node);
break;
case Ast_Kind_StrLit:
- (*expr)->type_node = symres_type(builtin_string_type);
+ symres_type(&builtin_string_type);
+ (*expr)->type_node = builtin_string_type;
break;
case Ast_Kind_Slice:
}
}
- func->return_type = symres_type(func->return_type);
+ symres_type(&func->return_type);
if (!node_is_type((AstNode *) func->return_type)) {
onyx_report_error(func->token->pos, "Return type is not a type.");
}
bh_arr_each(AstParam, param, func->params) {
if (param->local->type_node != NULL) {
- param->local->type_node = symres_type(param->local->type_node);
+ symres_type(¶m->local->type_node);
}
}
}
}
static void symres_global(AstGlobal* global) {
- global->type_node = symres_type(global->type_node);
+ symres_type(&global->type_node);
}
static void symres_overloaded_function(AstOverloadedFunction* ofunc) {
}
static void symres_memres_type(AstMemRes** memres) {
- (*memres)->type_node = symres_type((*memres)->type_node);
+ symres_type(&(*memres)->type_node);
}
static void symres_memres(AstMemRes** memres) {
bh_arr_each(AstPolyParam, param, pp->poly_params) {
if (param->kind != PPK_Baked_Value) continue;
- param->type_expr = symres_type(param->type_expr);
+ symres_type(¶m->type_expr);
}
// CLEANUP: This was copied from symres_function_header.
case Entity_Type_Overloaded_Function: symres_overloaded_function(ent->overloaded_function); break;
case Entity_Type_Expression: symres_expression(&ent->expr); break;
- case Entity_Type_Type_Alias: ent->type_alias = symres_type(ent->type_alias); break;
+ case Entity_Type_Type_Alias: symres_type(&ent->type_alias); break;
case Entity_Type_Enum: symres_enum(ent->enum_type); break;
case Entity_Type_Memory_Reservation_Type: symres_memres_type(&ent->mem_res); break;
case Entity_Type_Memory_Reservation: symres_memres(&ent->mem_res); break;