value : V;
}
+ init :: init
has :: has
get :: get
get_ptr :: get_ptr
Ast_Flag_Decl_Followed_By_Init = BH_BIT(20),
Ast_Flag_Param_Symbol_Dirty = BH_BIT(21),
+
+ Ast_Flag_Dead = BH_BIT(22),
} AstFlags;
typedef enum UnaryOp {
Table(AstSolidifiedFunction) concrete_funcs;
bh_imap active_queries;
+ bh_arr(AstNode *) nodes_that_need_entities_after_clone;
+
b32 is_exported : 1;
b32 is_foreign : 1;
b32 is_intrinsic : 1;
PolymorphicContext polymorph_context;
+ bh_arr(AstFunction *) current_function_stack;
Scope *current_scope;
bh_arr(bh_arr(Entity *) *) alternate_entity_placement_stack;
bh_arr(OnyxToken *) current_symbol_stack;
case Ast_Kind_Static_If: return sizeof(AstIfWhile);
case Ast_Kind_If_Expression: return sizeof(AstIfExpression);
case Ast_Kind_Directive_Insert: return sizeof(AstDirectiveInsert);
+ case Ast_Kind_Directive_Defined: return sizeof(AstDirectiveDefined);
case Ast_Kind_Do_Block: return sizeof(AstDoBlock);
case Ast_Kind_Constraint: return sizeof(AstConstraint);
case Ast_Kind_Count: return 0;
return root;
}
+static bh_arr(AstNode *) captured_entities=NULL;
+#define E(ent) do { \
+ assert(captured_entities); \
+ ent->entity = NULL; \
+ bh_arr_push(captured_entities, (AstNode *) ent); \
+ } while (0);
+
+
#define C(nt, mname) ((nt *) nn)->mname = (void *) ast_clone(a, ((nt *) node)->mname);
// NOTE: Using void* to avoid a lot of unnecessary casting
case Ast_Kind_If:
case Ast_Kind_While:
((AstIfWhile *) nn)->initialization = ast_clone_list(a, ((AstIfWhile *) node)->initialization);
-
- C(AstIfWhile, cond);
//fallthrough
case Ast_Kind_Static_If:
+ C(AstIfWhile, cond);
+
C(AstIfWhile, true_stmt);
C(AstIfWhile, false_stmt);
+
+ if (nn->kind == Ast_Kind_Static_If) {
+ ((AstIfWhile *) node)->flags |= Ast_Flag_Dead;
+ ((AstIfWhile *) node)->flags |= Ast_Flag_Static_If_Resolved;
+
+ ((AstIfWhile *) nn)->flags &= ~Ast_Flag_Dead;
+ ((AstIfWhile *) nn)->flags &= ~Ast_Flag_Static_If_Resolved;
+ E(nn);
+ }
+
break;
case Ast_Kind_Switch_Case: {
if (sf->is_foreign) return node;
assert(df->scope == NULL);
+ df->nodes_that_need_entities_after_clone = NULL;
+ bh_arr_new(global_heap_allocator, df->nodes_that_need_entities_after_clone, 1);
+ captured_entities = df->nodes_that_need_entities_after_clone;
+
df->return_type = (AstType *) ast_clone(a, sf->return_type);
df->body = (AstBlock *) ast_clone(a, sf->body);
+ df->nodes_that_need_entities_after_clone = captured_entities;
+ captured_entities = NULL;
+
df->params = NULL;
bh_arr_new(global_heap_allocator, df->params, bh_arr_length(sf->params));
C(AstDirectiveInsert, code_expr);
break;
+ case Ast_Kind_Directive_Defined:
+ C(AstDirectiveDefined, expr);
+ ((AstDirectiveDefined *) nn)->is_defined = 0;
+ break;
+
case Ast_Kind_Typeof:
C(AstTypeOf, expr);
((AstTypeOf *) nn)->resolved_type = NULL;
if (dest->kind != Ast_Kind_Function) return;
if (source->kind != Ast_Kind_Polymorphic_Proc && source->kind != Ast_Kind_Function) return;
+ dest->nodes_that_need_entities_after_clone = NULL;
+ bh_arr_new(global_heap_allocator, dest->nodes_that_need_entities_after_clone, 1);
+ captured_entities = dest->nodes_that_need_entities_after_clone;
+
dest->body = (AstBlock *) ast_clone(a, source->body);
+
+ dest->nodes_that_need_entities_after_clone = captured_entities;
+ captured_entities = NULL;
}
if (next_tokens_are(parser, 2, '#', Token_Type_Keyword_If)) {
AstIf* static_if = parse_static_if_stmt(parser, 1);
- ENTITY_SUBMIT(static_if);
+
+ assert(parser->current_function_stack && bh_arr_length(parser->current_function_stack) > 0);
+ bh_arr_push(bh_arr_last(parser->current_function_stack)->nodes_that_need_entities_after_clone, (AstNode *) static_if);
needs_semicolon = 0;
retval = (AstNode *) static_if;
static AstFunction* parse_function_definition(OnyxParser* parser, OnyxToken* token) {
AstFunction* func_def = make_node(AstFunction, Ast_Kind_Function);
func_def->token = token;
+ bh_arr_push(parser->current_function_stack, func_def);
bh_arr_new(global_heap_allocator, func_def->params, 4);
bh_arr_free(polymorphic_vars);
}
+ bh_arr_pop(parser->current_function_stack);
return func_def;
}
AstBlock* body_block;
AstType* return_type;
+ bh_arr_push(parser->current_function_stack, poly_proc);
if (parser->curr->type == '{') {
char* name = NULL;
*ret = (AstTyped *) poly_proc;
+ bh_arr_pop(parser->current_function_stack);
bh_arr_free(params);
bh_arr_free(poly_params);
return 1;
parser.current_scope = NULL;
parser.alternate_entity_placement_stack = NULL;
parser.current_symbol_stack = NULL;
+ parser.current_function_stack = NULL;
parser.scope_flags = NULL;
parser.parse_calls = 1;
AstTyped* expr = (AstTyped *) strip_aliases((AstNode *) (*fa)->expr);
b32 force_a_lookup = 0;
- if (expr->kind == Ast_Kind_Enum_Type) {
+ if (expr->kind == Ast_Kind_Enum_Type || expr->kind == Ast_Kind_Type_Raw_Alias) {
force_a_lookup = 1;
}
static SymresStatus symres_if(AstIfWhile* ifnode) {
if (ifnode->kind == Ast_Kind_Static_If) {
if ((ifnode->flags & Ast_Flag_Static_If_Resolved) == 0) {
- return Symres_Yield_Macro;
+ if (context.cycle_detected) {
+ onyx_report_error(ifnode->token->pos, Error_Waiting_On, "Waiting on static if resolution.");
+ return Symres_Error;
+ } else {
+ return Symres_Yield_Macro;
+ }
}
if (static_if_resolution(ifnode)) {
b32 use_package_count = (context.entities.type_count[Entity_Type_Use_Package] == 0);
+ resolved_a_symbol = 0;
SymresStatus ss = symres_expression(&defined->expr);
- if (use_package_count && ss != Symres_Success) {
+ if (use_package_count && ss != Symres_Success && !resolved_a_symbol) {
// The symbol definitely was not found and there is no chance that it could be found.
defined->is_defined = 0;
return Symres_Success;
return Symres_Complete;
}
+ if (func->nodes_that_need_entities_after_clone && bh_arr_length(func->nodes_that_need_entities_after_clone) > 0) {
+ bh_arr_each(AstNode *, node, func->nodes_that_need_entities_after_clone) {
+ // Need to curr_scope->parent because curr_scope is the function body scope.
+ add_entities_for_node(NULL, *node, curr_scope->parent, func->entity->package);
+ }
+
+ bh_arr_set_length(func->nodes_that_need_entities_after_clone, 0);
+ }
+
SYMRES(type, &func->return_type);
if (func->constraints.constraints != NULL) {
}
static SymresStatus symres_static_if(AstIf* static_if) {
+ if (static_if->flags & Ast_Flag_Dead) return Symres_Complete;
+
SYMRES(expression, &static_if->cond);
return Symres_Success;
}
case Ast_Kind_Struct_Type: {
AstStructType* stype = (AstStructType *) node;
- AstNode* result = symbol_raw_resolve(stype->scope, symbol);
+
+ // HACK HACK
+ // Temporarily disable the parent scope so that you can't access things
+ // "above" the structures scope. This leads to unintended behavior, as when
+ // you are accessing a static element on a structure, you don't expect to
+ // bleed to the top level scope.
+ AstNode *result = NULL;
+ if (stype->scope) {
+ Scope *tmp_parent = stype->scope->parent;
+ stype->scope->parent = NULL;
+ result = symbol_raw_resolve(stype->scope, symbol);
+ stype->scope->parent = tmp_parent;
+ }
if (result == NULL && stype->stcache != NULL) {
Type* struct_type = stype->stcache;