mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Big renaming: AstNode to Ast
This commit is contained in:
+35
-35
@@ -1,5 +1,5 @@
|
|||||||
bool check_is_terminating(AstNode *node);
|
bool check_is_terminating(Ast *node);
|
||||||
void check_stmt (CheckerContext *ctx, AstNode *node, u32 flags);
|
void check_stmt (CheckerContext *ctx, Ast *node, u32 flags);
|
||||||
|
|
||||||
// NOTE(bill): 'content_name' is for debugging and error messages
|
// NOTE(bill): 'content_name' is for debugging and error messages
|
||||||
Type *check_init_variable(CheckerContext *ctx, Entity *e, Operand *operand, String context_name) {
|
Type *check_init_variable(CheckerContext *ctx, Entity *e, Operand *operand, String context_name) {
|
||||||
@@ -89,7 +89,7 @@ Type *check_init_variable(CheckerContext *ctx, Entity *e, Operand *operand, Stri
|
|||||||
return e->type;
|
return e->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_init_variables(CheckerContext *ctx, Entity **lhs, isize lhs_count, Array<AstNode *> const &inits, String context_name) {
|
void check_init_variables(CheckerContext *ctx, Entity **lhs, isize lhs_count, Array<Ast *> const &inits, String context_name) {
|
||||||
if ((lhs == nullptr || lhs_count == 0) && inits.count == 0) {
|
if ((lhs == nullptr || lhs_count == 0) && inits.count == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -168,14 +168,14 @@ void check_init_constant(CheckerContext *ctx, Entity *e, Operand *operand) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool is_type_distinct(AstNode *node) {
|
bool is_type_distinct(Ast *node) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (node == nullptr) {
|
if (node == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (node->kind == AstNode_ParenExpr) {
|
if (node->kind == Ast_ParenExpr) {
|
||||||
node = node->ParenExpr.expr;
|
node = node->ParenExpr.expr;
|
||||||
} else if (node->kind == AstNode_HelperType) {
|
} else if (node->kind == Ast_HelperType) {
|
||||||
node = node->HelperType.type;
|
node = node->HelperType.type;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@@ -183,33 +183,33 @@ bool is_type_distinct(AstNode *node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (node->kind) {
|
switch (node->kind) {
|
||||||
case AstNode_DistinctType:
|
case Ast_DistinctType:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case AstNode_StructType:
|
case Ast_StructType:
|
||||||
case AstNode_UnionType:
|
case Ast_UnionType:
|
||||||
case AstNode_EnumType:
|
case Ast_EnumType:
|
||||||
case AstNode_BitFieldType:
|
case Ast_BitFieldType:
|
||||||
case AstNode_ProcType:
|
case Ast_ProcType:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case AstNode_PointerType:
|
case Ast_PointerType:
|
||||||
case AstNode_ArrayType:
|
case Ast_ArrayType:
|
||||||
case AstNode_DynamicArrayType:
|
case Ast_DynamicArrayType:
|
||||||
case AstNode_MapType:
|
case Ast_MapType:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *remove_type_alias_clutter(AstNode *node) {
|
Ast *remove_type_alias_clutter(Ast *node) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (node == nullptr) {
|
if (node == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (node->kind == AstNode_ParenExpr) {
|
if (node->kind == Ast_ParenExpr) {
|
||||||
node = node->ParenExpr.expr;
|
node = node->ParenExpr.expr;
|
||||||
} else if (node->kind == AstNode_DistinctType) {
|
} else if (node->kind == Ast_DistinctType) {
|
||||||
node = node->DistinctType.type;
|
node = node->DistinctType.type;
|
||||||
} else {
|
} else {
|
||||||
return node;
|
return node;
|
||||||
@@ -217,7 +217,7 @@ AstNode *remove_type_alias_clutter(AstNode *node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_type_decl(CheckerContext *ctx, Entity *e, AstNode *type_expr, Type *def) {
|
void check_type_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Type *def) {
|
||||||
GB_ASSERT(e->type == nullptr);
|
GB_ASSERT(e->type == nullptr);
|
||||||
|
|
||||||
DeclInfo *decl = decl_info_of_entity(e);
|
DeclInfo *decl = decl_info_of_entity(e);
|
||||||
@@ -228,7 +228,7 @@ void check_type_decl(CheckerContext *ctx, Entity *e, AstNode *type_expr, Type *d
|
|||||||
|
|
||||||
|
|
||||||
bool is_distinct = is_type_distinct(type_expr);
|
bool is_distinct = is_type_distinct(type_expr);
|
||||||
AstNode *te = remove_type_alias_clutter(type_expr);
|
Ast *te = remove_type_alias_clutter(type_expr);
|
||||||
e->type = t_invalid;
|
e->type = t_invalid;
|
||||||
String name = e->token.string;
|
String name = e->token.string;
|
||||||
Type *named = alloc_type_named(name, nullptr, e);
|
Type *named = alloc_type_named(name, nullptr, e);
|
||||||
@@ -263,7 +263,7 @@ void override_entity_in_scope(Entity *original_entity, Entity *new_entity) {
|
|||||||
map_set(&found_scope->elements, hash_string(original_name), new_entity);
|
map_set(&found_scope->elements, hash_string(original_name), new_entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_const_decl(CheckerContext *ctx, Entity *e, AstNode *type_expr, AstNode *init, Type *named_type) {
|
void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init, Type *named_type) {
|
||||||
GB_ASSERT(e->type == nullptr);
|
GB_ASSERT(e->type == nullptr);
|
||||||
GB_ASSERT(e->kind == Entity_Constant);
|
GB_ASSERT(e->kind == Entity_Constant);
|
||||||
|
|
||||||
@@ -289,9 +289,9 @@ void check_const_decl(CheckerContext *ctx, Entity *e, AstNode *type_expr, AstNod
|
|||||||
|
|
||||||
if (init != nullptr) {
|
if (init != nullptr) {
|
||||||
Entity *entity = nullptr;
|
Entity *entity = nullptr;
|
||||||
if (init->kind == AstNode_Ident) {
|
if (init->kind == Ast_Ident) {
|
||||||
entity = check_ident(ctx, &operand, init, nullptr, e->type, true);
|
entity = check_ident(ctx, &operand, init, nullptr, e->type, true);
|
||||||
} else if (init->kind == AstNode_SelectorExpr) {
|
} else if (init->kind == Ast_SelectorExpr) {
|
||||||
entity = check_selector(ctx, &operand, init, e->type);
|
entity = check_selector(ctx, &operand, init, e->type);
|
||||||
} else {
|
} else {
|
||||||
check_expr_or_type(ctx, &operand, init, e->type);
|
check_expr_or_type(ctx, &operand, init, e->type);
|
||||||
@@ -413,7 +413,7 @@ bool are_signatures_similar_enough(Type *a_, Type *b_) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void init_entity_foreign_library(CheckerContext *ctx, Entity *e) {
|
void init_entity_foreign_library(CheckerContext *ctx, Entity *e) {
|
||||||
AstNode *ident = nullptr;
|
Ast *ident = nullptr;
|
||||||
Entity **foreign_library = nullptr;
|
Entity **foreign_library = nullptr;
|
||||||
|
|
||||||
switch (e->kind) {
|
switch (e->kind) {
|
||||||
@@ -431,7 +431,7 @@ void init_entity_foreign_library(CheckerContext *ctx, Entity *e) {
|
|||||||
|
|
||||||
if (ident == nullptr) {
|
if (ident == nullptr) {
|
||||||
error(e->token, "foreign entiies must declare which library they are from");
|
error(e->token, "foreign entiies must declare which library they are from");
|
||||||
} else if (ident->kind != AstNode_Ident) {
|
} else if (ident->kind != Ast_Ident) {
|
||||||
error(ident, "foreign library names must be an identifier");
|
error(ident, "foreign library names must be an identifier");
|
||||||
} else {
|
} else {
|
||||||
String name = ident->Ident.token.string;
|
String name = ident->Ident.token.string;
|
||||||
@@ -472,7 +472,7 @@ String handle_link_name(CheckerContext *ctx, Token token, String link_name, Stri
|
|||||||
|
|
||||||
void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
||||||
GB_ASSERT(e->type == nullptr);
|
GB_ASSERT(e->type == nullptr);
|
||||||
if (d->proc_lit->kind != AstNode_ProcLit) {
|
if (d->proc_lit->kind != Ast_ProcLit) {
|
||||||
// TOOD(bill): Better error message
|
// TOOD(bill): Better error message
|
||||||
error(d->proc_lit, "Expected a procedure to check");
|
error(d->proc_lit, "Expected a procedure to check");
|
||||||
return;
|
return;
|
||||||
@@ -556,7 +556,7 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
|||||||
|
|
||||||
d->scope = ctx->scope;
|
d->scope = ctx->scope;
|
||||||
|
|
||||||
GB_ASSERT(pl->body->kind == AstNode_BlockStmt);
|
GB_ASSERT(pl->body->kind == Ast_BlockStmt);
|
||||||
if (!pt->is_polymorphic) {
|
if (!pt->is_polymorphic) {
|
||||||
check_procedure_later(ctx->checker, ctx->file, e->token, d, proc_type, pl->body, pl->tags);
|
check_procedure_later(ctx->checker, ctx->file, e->token, d, proc_type, pl->body, pl->tags);
|
||||||
}
|
}
|
||||||
@@ -640,7 +640,7 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_var_decl(CheckerContext *ctx, Entity *e, Entity **entities, isize entity_count, AstNode *type_expr, Array<AstNode *> const &init_expr_list) {
|
void check_var_decl(CheckerContext *ctx, Entity *e, Entity **entities, isize entity_count, Ast *type_expr, Array<Ast *> const &init_expr_list) {
|
||||||
GB_ASSERT(e->type == nullptr);
|
GB_ASSERT(e->type == nullptr);
|
||||||
GB_ASSERT(e->kind == Entity_Variable);
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
|
|
||||||
@@ -749,16 +749,16 @@ void check_proc_group_decl(CheckerContext *ctx, Entity *pg_entity, DeclInfo *d)
|
|||||||
ptr_set_init(&entity_set, heap_allocator(), 2*pg->args.count);
|
ptr_set_init(&entity_set, heap_allocator(), 2*pg->args.count);
|
||||||
|
|
||||||
for_array(i, pg->args) {
|
for_array(i, pg->args) {
|
||||||
AstNode *arg = pg->args[i];
|
Ast *arg = pg->args[i];
|
||||||
Entity *e = nullptr;
|
Entity *e = nullptr;
|
||||||
Operand o = {};
|
Operand o = {};
|
||||||
if (arg->kind == AstNode_Ident) {
|
if (arg->kind == Ast_Ident) {
|
||||||
e = check_ident(ctx, &o, arg, nullptr, nullptr, true);
|
e = check_ident(ctx, &o, arg, nullptr, nullptr, true);
|
||||||
} else if (arg->kind == AstNode_SelectorExpr) {
|
} else if (arg->kind == Ast_SelectorExpr) {
|
||||||
e = check_selector(ctx, &o, arg, nullptr);
|
e = check_selector(ctx, &o, arg, nullptr);
|
||||||
}
|
}
|
||||||
if (e == nullptr) {
|
if (e == nullptr) {
|
||||||
error(arg, "Expected a valid entity name in procedure group, got %.*s", LIT(ast_node_strings[arg->kind]));
|
error(arg, "Expected a valid entity name in procedure group, got %.*s", LIT(ast_strings[arg->kind]));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (e->kind == Entity_Variable) {
|
if (e->kind == Entity_Variable) {
|
||||||
@@ -919,11 +919,11 @@ void check_entity_decl(CheckerContext *ctx, Entity *e, DeclInfo *d, Type *named_
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *type, AstNode *body) {
|
void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *type, Ast *body) {
|
||||||
if (body == nullptr) {
|
if (body == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GB_ASSERT(body->kind == AstNode_BlockStmt);
|
GB_ASSERT(body->kind == Ast_BlockStmt);
|
||||||
|
|
||||||
String proc_name = {};
|
String proc_name = {};
|
||||||
if (token.kind == Token_Ident) {
|
if (token.kind == Token_Ident) {
|
||||||
|
|||||||
+154
-154
@@ -45,40 +45,40 @@ int valid_index_and_score_cmp(void const *a, void const *b) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define CALL_ARGUMENT_CHECKER(name) CallArgumentError name(CheckerContext *c, AstNode *call, Type *proc_type, Entity *entity, Array<Operand> operands, CallArgumentErrorMode show_error_mode, CallArgumentData *data)
|
#define CALL_ARGUMENT_CHECKER(name) CallArgumentError name(CheckerContext *c, Ast *call, Type *proc_type, Entity *entity, Array<Operand> operands, CallArgumentErrorMode show_error_mode, CallArgumentData *data)
|
||||||
typedef CALL_ARGUMENT_CHECKER(CallArgumentCheckerType);
|
typedef CALL_ARGUMENT_CHECKER(CallArgumentCheckerType);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void check_expr (CheckerContext *c, Operand *operand, AstNode *expression);
|
void check_expr (CheckerContext *c, Operand *operand, Ast *expression);
|
||||||
void check_multi_expr (CheckerContext *c, Operand *operand, AstNode *expression);
|
void check_multi_expr (CheckerContext *c, Operand *operand, Ast *expression);
|
||||||
void check_expr_or_type (CheckerContext *c, Operand *operand, AstNode *expression, Type *type_hint = nullptr);
|
void check_expr_or_type (CheckerContext *c, Operand *operand, Ast *expression, Type *type_hint = nullptr);
|
||||||
ExprKind check_expr_base (CheckerContext *c, Operand *operand, AstNode *expression, Type *type_hint);
|
ExprKind check_expr_base (CheckerContext *c, Operand *operand, Ast *expression, Type *type_hint);
|
||||||
void check_expr_with_type_hint (CheckerContext *c, Operand *o, AstNode *e, Type *t);
|
void check_expr_with_type_hint (CheckerContext *c, Operand *o, Ast *e, Type *t);
|
||||||
Type * check_type (CheckerContext *c, AstNode *expression);
|
Type * check_type (CheckerContext *c, Ast *expression);
|
||||||
Type * check_type_expr (CheckerContext *c, AstNode *expression, Type *named_type);
|
Type * check_type_expr (CheckerContext *c, Ast *expression, Type *named_type);
|
||||||
Type * make_optional_ok_type (Type *value);
|
Type * make_optional_ok_type (Type *value);
|
||||||
void check_type_decl (CheckerContext *c, Entity *e, AstNode *type_expr, Type *def);
|
void check_type_decl (CheckerContext *c, Entity *e, Ast *type_expr, Type *def);
|
||||||
Entity * check_selector (CheckerContext *c, Operand *operand, AstNode *node, Type *type_hint);
|
Entity * check_selector (CheckerContext *c, Operand *operand, Ast *node, Type *type_hint);
|
||||||
Entity * check_ident (CheckerContext *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint, bool allow_import_name);
|
Entity * check_ident (CheckerContext *c, Operand *o, Ast *n, Type *named_type, Type *type_hint, bool allow_import_name);
|
||||||
Entity * find_polymorphic_struct_entity (CheckerContext *c, Type *original_type, isize param_count, Array<Operand> ordered_operands);
|
Entity * find_polymorphic_struct_entity (CheckerContext *c, Type *original_type, isize param_count, Array<Operand> ordered_operands);
|
||||||
void check_not_tuple (CheckerContext *c, Operand *operand);
|
void check_not_tuple (CheckerContext *c, Operand *operand);
|
||||||
void convert_to_typed (CheckerContext *c, Operand *operand, Type *target_type);
|
void convert_to_typed (CheckerContext *c, Operand *operand, Type *target_type);
|
||||||
gbString expr_to_string (AstNode *expression);
|
gbString expr_to_string (Ast *expression);
|
||||||
void check_entity_decl (CheckerContext *c, Entity *e, DeclInfo *decl, Type *named_type);
|
void check_entity_decl (CheckerContext *c, Entity *e, DeclInfo *decl, Type *named_type);
|
||||||
void check_const_decl (CheckerContext *c, Entity *e, AstNode *type_expr, AstNode *init_expr, Type *named_type);
|
void check_const_decl (CheckerContext *c, Entity *e, Ast *type_expr, Ast *init_expr, Type *named_type);
|
||||||
void check_proc_body (CheckerContext *c, Token token, DeclInfo *decl, Type *type, AstNode *body);
|
void check_proc_body (CheckerContext *c, Token token, DeclInfo *decl, Type *type, Ast *body);
|
||||||
void update_expr_type (CheckerContext *c, AstNode *e, Type *type, bool final);
|
void update_expr_type (CheckerContext *c, Ast *e, Type *type, bool final);
|
||||||
bool check_is_terminating (AstNode *node);
|
bool check_is_terminating (Ast *node);
|
||||||
bool check_has_break (AstNode *stmt, bool implicit);
|
bool check_has_break (Ast *stmt, bool implicit);
|
||||||
void check_stmt (CheckerContext *c, AstNode *node, u32 flags);
|
void check_stmt (CheckerContext *c, Ast *node, u32 flags);
|
||||||
void check_stmt_list (CheckerContext *c, Array<AstNode *> const &stmts, u32 flags);
|
void check_stmt_list (CheckerContext *c, Array<Ast *> const &stmts, u32 flags);
|
||||||
void check_init_constant (CheckerContext *c, Entity *e, Operand *operand);
|
void check_init_constant (CheckerContext *c, Entity *e, Operand *operand);
|
||||||
bool check_representable_as_constant(CheckerContext *c, ExactValue in_value, Type *type, ExactValue *out_value);
|
bool check_representable_as_constant(CheckerContext *c, ExactValue in_value, Type *type, ExactValue *out_value);
|
||||||
bool check_procedure_type (CheckerContext *c, Type *type, AstNode *proc_type_node, Array<Operand> *operands = nullptr);
|
bool check_procedure_type (CheckerContext *c, Type *type, Ast *proc_type_node, Array<Operand> *operands = nullptr);
|
||||||
void check_struct_type (CheckerContext *c, Type *struct_type, AstNode *node, Array<Operand> *poly_operands,
|
void check_struct_type (CheckerContext *c, Type *struct_type, Ast *node, Array<Operand> *poly_operands,
|
||||||
Type *named_type = nullptr, Type *original_type_for_poly = nullptr);
|
Type *named_type = nullptr, Type *original_type_for_poly = nullptr);
|
||||||
CallArgumentData check_call_arguments (CheckerContext *c, Operand *operand, Type *proc_type, AstNode *call);
|
CallArgumentData check_call_arguments (CheckerContext *c, Operand *operand, Type *proc_type, Ast *call);
|
||||||
Type * check_init_variable (CheckerContext *c, Entity *e, Operand *operand, String context_name);
|
Type * check_init_variable (CheckerContext *c, Entity *e, Operand *operand, String context_name);
|
||||||
|
|
||||||
|
|
||||||
@@ -95,8 +95,8 @@ void error_operand_not_expression(Operand *o) {
|
|||||||
void error_operand_no_value(Operand *o) {
|
void error_operand_no_value(Operand *o) {
|
||||||
if (o->mode == Addressing_NoValue) {
|
if (o->mode == Addressing_NoValue) {
|
||||||
gbString err = expr_to_string(o->expr);
|
gbString err = expr_to_string(o->expr);
|
||||||
AstNode *x = unparen_expr(o->expr);
|
Ast *x = unparen_expr(o->expr);
|
||||||
if (x->kind == AstNode_CallExpr) {
|
if (x->kind == Ast_CallExpr) {
|
||||||
error(o->expr, "'%s' call does not return a value and cannot be used as a value", err);
|
error(o->expr, "'%s' call does not return a value and cannot be used as a value", err);
|
||||||
} else {
|
} else {
|
||||||
error(o->expr, "'%s' used as a value", err);
|
error(o->expr, "'%s' used as a value", err);
|
||||||
@@ -107,7 +107,7 @@ void error_operand_no_value(Operand *o) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_scope_decls(CheckerContext *c, Array<AstNode *> const &nodes, isize reserve_size) {
|
void check_scope_decls(CheckerContext *c, Array<Ast *> const &nodes, isize reserve_size) {
|
||||||
Scope *s = c->scope;
|
Scope *s = c->scope;
|
||||||
GB_ASSERT(s->package == nullptr);
|
GB_ASSERT(s->package == nullptr);
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ bool check_is_assignable_to_using_subtype(Type *src, Type *dst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_entity, Type *type,
|
bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_entity, Type *type,
|
||||||
Array<Operand> *param_operands, AstNode *poly_def_node, PolyProcData *poly_proc_data) {
|
Array<Operand> *param_operands, Ast *poly_def_node, PolyProcData *poly_proc_data) {
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
// TODO CLEANUP(bill): This procedure is very messy and hacky. Clean this!!! //
|
// TODO CLEANUP(bill): This procedure is very messy and hacky. Clean this!!! //
|
||||||
@@ -316,7 +316,7 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
AstNode *proc_lit = clone_ast_node(a, old_decl->proc_lit);
|
Ast *proc_lit = clone_ast_node(a, old_decl->proc_lit);
|
||||||
ast_node(pl, ProcLit, proc_lit);
|
ast_node(pl, ProcLit, proc_lit);
|
||||||
// NOTE(bill): Associate the scope declared above withinth this procedure declaration's type
|
// NOTE(bill): Associate the scope declared above withinth this procedure declaration's type
|
||||||
add_scope(&nctx, pl->type, final_proc_type->Proc.scope);
|
add_scope(&nctx, pl->type, final_proc_type->Proc.scope);
|
||||||
@@ -335,7 +335,7 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti
|
|||||||
}
|
}
|
||||||
|
|
||||||
u64 tags = base_entity->Procedure.tags;
|
u64 tags = base_entity->Procedure.tags;
|
||||||
AstNode *ident = clone_ast_node(a, base_entity->identifier);
|
Ast *ident = clone_ast_node(a, base_entity->identifier);
|
||||||
Token token = ident->Ident.token;
|
Token token = ident->Ident.token;
|
||||||
DeclInfo *d = make_decl_info(nctx.allocator, scope, old_decl->parent);
|
DeclInfo *d = make_decl_info(nctx.allocator, scope, old_decl->parent);
|
||||||
d->gen_proc_type = final_proc_type;
|
d->gen_proc_type = final_proc_type;
|
||||||
@@ -390,14 +390,14 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_polymorphic_procedure_assignment(CheckerContext *c, Operand *operand, Type *type, AstNode *poly_def_node, PolyProcData *poly_proc_data) {
|
bool check_polymorphic_procedure_assignment(CheckerContext *c, Operand *operand, Type *type, Ast *poly_def_node, PolyProcData *poly_proc_data) {
|
||||||
if (operand->expr == nullptr) return false;
|
if (operand->expr == nullptr) return false;
|
||||||
Entity *base_entity = entity_of_ident(operand->expr);
|
Entity *base_entity = entity_of_ident(operand->expr);
|
||||||
if (base_entity == nullptr) return false;
|
if (base_entity == nullptr) return false;
|
||||||
return find_or_generate_polymorphic_procedure(c, base_entity, type, nullptr, poly_def_node, poly_proc_data);
|
return find_or_generate_polymorphic_procedure(c, base_entity, type, nullptr, poly_def_node, poly_proc_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool find_or_generate_polymorphic_procedure_from_parameters(CheckerContext *c, Entity *base_entity, Array<Operand> *operands, AstNode *poly_def_node, PolyProcData *poly_proc_data) {
|
bool find_or_generate_polymorphic_procedure_from_parameters(CheckerContext *c, Entity *base_entity, Array<Operand> *operands, Ast *poly_def_node, PolyProcData *poly_proc_data) {
|
||||||
return find_or_generate_polymorphic_procedure(c, base_entity, nullptr, operands, poly_def_node, poly_proc_data);
|
return find_or_generate_polymorphic_procedure(c, base_entity, nullptr, operands, poly_def_node, poly_proc_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,8 +590,8 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *expr = unparen_expr(operand->expr);
|
Ast *expr = unparen_expr(operand->expr);
|
||||||
if (expr != nullptr && expr->kind == AstNode_AutoCast) {
|
if (expr != nullptr && expr->kind == Ast_AutoCast) {
|
||||||
Operand x = *operand;
|
Operand x = *operand;
|
||||||
x.expr = expr->AutoCast.expr;
|
x.expr = expr->AutoCast.expr;
|
||||||
bool ok = check_cast_internal(c, &x, type);
|
bool ok = check_cast_internal(c, &x, type);
|
||||||
@@ -940,8 +940,8 @@ bool check_cycle(CheckerContext *c, Entity *curr, bool report) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Entity *check_ident(CheckerContext *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint, bool allow_import_name) {
|
Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Type *type_hint, bool allow_import_name) {
|
||||||
GB_ASSERT(n->kind == AstNode_Ident);
|
GB_ASSERT(n->kind == Ast_Ident);
|
||||||
o->mode = Addressing_Invalid;
|
o->mode = Addressing_Invalid;
|
||||||
o->expr = n;
|
o->expr = n;
|
||||||
String name = n->Ident.token.string;
|
String name = n->Ident.token.string;
|
||||||
@@ -1381,8 +1381,8 @@ void check_is_expressible(CheckerContext *c, Operand *o, Type *type) {
|
|||||||
|
|
||||||
bool check_is_not_addressable(CheckerContext *c, Operand *o) {
|
bool check_is_not_addressable(CheckerContext *c, Operand *o) {
|
||||||
if (o->mode == Addressing_OptionalOk) {
|
if (o->mode == Addressing_OptionalOk) {
|
||||||
AstNode *expr = unselector_expr(o->expr);
|
Ast *expr = unselector_expr(o->expr);
|
||||||
if (expr->kind != AstNode_TypeAssertion) {
|
if (expr->kind != Ast_TypeAssertion) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
ast_node(ta, TypeAssertion, expr);
|
ast_node(ta, TypeAssertion, expr);
|
||||||
@@ -1409,11 +1409,11 @@ bool check_is_not_addressable(CheckerContext *c, Operand *o) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_unary_expr(CheckerContext *c, Operand *o, Token op, AstNode *node) {
|
void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast *node) {
|
||||||
switch (op.kind) {
|
switch (op.kind) {
|
||||||
case Token_And: { // Pointer address
|
case Token_And: { // Pointer address
|
||||||
if (check_is_not_addressable(c, o)) {
|
if (check_is_not_addressable(c, o)) {
|
||||||
if (ast_node_expect(node, AstNode_UnaryExpr)) {
|
if (ast_node_expect(node, Ast_UnaryExpr)) {
|
||||||
ast_node(ue, UnaryExpr, node);
|
ast_node(ue, UnaryExpr, node);
|
||||||
gbString str = expr_to_string(ue->expr);
|
gbString str = expr_to_string(ue->expr);
|
||||||
error(op, "Cannot take the pointer address of '%s'", str);
|
error(op, "Cannot take the pointer address of '%s'", str);
|
||||||
@@ -1594,8 +1594,8 @@ void check_comparison(CheckerContext *c, Operand *x, Operand *y, TokenKind op) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_shift(CheckerContext *c, Operand *x, Operand *y, AstNode *node) {
|
void check_shift(CheckerContext *c, Operand *x, Operand *y, Ast *node) {
|
||||||
GB_ASSERT(node->kind == AstNode_BinaryExpr);
|
GB_ASSERT(node->kind == Ast_BinaryExpr);
|
||||||
ast_node(be, BinaryExpr, node);
|
ast_node(be, BinaryExpr, node);
|
||||||
|
|
||||||
ExactValue x_val = {};
|
ExactValue x_val = {};
|
||||||
@@ -1663,7 +1663,7 @@ void check_shift(CheckerContext *c, Operand *x, Operand *y, AstNode *node) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenPos pos = ast_node_token(x->expr).pos;
|
TokenPos pos = ast_token(x->expr).pos;
|
||||||
if (x_is_untyped) {
|
if (x_is_untyped) {
|
||||||
ExprInfo *info = check_get_expr_info(&c->checker->info, x->expr);
|
ExprInfo *info = check_get_expr_info(&c->checker->info, x->expr);
|
||||||
if (info != nullptr) {
|
if (info != nullptr) {
|
||||||
@@ -1693,8 +1693,8 @@ void check_shift(CheckerContext *c, Operand *x, Operand *y, AstNode *node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Operand check_ptr_addition(CheckerContext *c, TokenKind op, Operand *ptr, Operand *offset, AstNode *node) {
|
Operand check_ptr_addition(CheckerContext *c, TokenKind op, Operand *ptr, Operand *offset, Ast *node) {
|
||||||
GB_ASSERT(node->kind == AstNode_BinaryExpr);
|
GB_ASSERT(node->kind == Ast_BinaryExpr);
|
||||||
ast_node(be, BinaryExpr, node);
|
ast_node(be, BinaryExpr, node);
|
||||||
GB_ASSERT(is_type_pointer(ptr->type));
|
GB_ASSERT(is_type_pointer(ptr->type));
|
||||||
GB_ASSERT(is_type_integer(offset->type));
|
GB_ASSERT(is_type_integer(offset->type));
|
||||||
@@ -1933,7 +1933,7 @@ void check_cast(CheckerContext *c, Operand *x, Type *type) {
|
|||||||
x->type = type;
|
x->type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_transmute(CheckerContext *c, AstNode *node, Operand *o, Type *t) {
|
bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) {
|
||||||
if (!is_operand_value(*o)) {
|
if (!is_operand_value(*o)) {
|
||||||
error(o->expr, "'transmute' can only be applied to values");
|
error(o->expr, "'transmute' can only be applied to values");
|
||||||
o->mode = Addressing_Invalid;
|
o->mode = Addressing_Invalid;
|
||||||
@@ -1988,8 +1988,8 @@ bool check_binary_array_expr(CheckerContext *c, Token op, Operand *x, Operand *y
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_binary_expr(CheckerContext *c, Operand *x, AstNode *node) {
|
void check_binary_expr(CheckerContext *c, Operand *x, Ast *node) {
|
||||||
GB_ASSERT(node->kind == AstNode_BinaryExpr);
|
GB_ASSERT(node->kind == Ast_BinaryExpr);
|
||||||
Operand y_ = {}, *y = &y_;
|
Operand y_ = {}, *y = &y_;
|
||||||
|
|
||||||
ast_node(be, BinaryExpr, node);
|
ast_node(be, BinaryExpr, node);
|
||||||
@@ -2176,7 +2176,7 @@ void check_binary_expr(CheckerContext *c, Operand *x, AstNode *node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void update_expr_type(CheckerContext *c, AstNode *e, Type *type, bool final) {
|
void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) {
|
||||||
ExprInfo *found = check_get_expr_info(&c->checker->info, e);
|
ExprInfo *found = check_get_expr_info(&c->checker->info, e);
|
||||||
if (found == nullptr) {
|
if (found == nullptr) {
|
||||||
return;
|
return;
|
||||||
@@ -2235,7 +2235,7 @@ void update_expr_type(CheckerContext *c, AstNode *e, Type *type, bool final) {
|
|||||||
add_type_and_value(&c->checker->info, e, old.mode, type, old.value);
|
add_type_and_value(&c->checker->info, e, old.mode, type, old.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_expr_value(CheckerContext *c, AstNode *e, ExactValue value) {
|
void update_expr_value(CheckerContext *c, Ast *e, ExactValue value) {
|
||||||
ExprInfo *found = check_get_expr_info(&c->checker->info, e);
|
ExprInfo *found = check_get_expr_info(&c->checker->info, e);
|
||||||
if (found) {
|
if (found) {
|
||||||
found->value = value;
|
found->value = value;
|
||||||
@@ -2473,7 +2473,7 @@ void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) {
|
|||||||
update_expr_type(c, operand->expr, target_type, true);
|
update_expr_type(c, operand->expr, target_type, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_index_value(CheckerContext *c, bool open_range, AstNode *index_value, i64 max_count, i64 *value) {
|
bool check_index_value(CheckerContext *c, bool open_range, Ast *index_value, i64 max_count, i64 *value) {
|
||||||
Operand operand = {Addressing_Invalid};
|
Operand operand = {Addressing_Invalid};
|
||||||
check_expr(c, &operand, index_value);
|
check_expr(c, &operand, index_value);
|
||||||
if (operand.mode == Addressing_Invalid) {
|
if (operand.mode == Addressing_Invalid) {
|
||||||
@@ -2531,7 +2531,7 @@ bool check_index_value(CheckerContext *c, bool open_range, AstNode *index_value,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity *check_selector(CheckerContext *c, Operand *operand, AstNode *node, Type *type_hint) {
|
Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *type_hint) {
|
||||||
ast_node(se, SelectorExpr, node);
|
ast_node(se, SelectorExpr, node);
|
||||||
|
|
||||||
bool check_op_expr = true;
|
bool check_op_expr = true;
|
||||||
@@ -2541,30 +2541,30 @@ Entity *check_selector(CheckerContext *c, Operand *operand, AstNode *node, Type
|
|||||||
|
|
||||||
operand->expr = node;
|
operand->expr = node;
|
||||||
|
|
||||||
AstNode *op_expr = se->expr;
|
Ast *op_expr = se->expr;
|
||||||
AstNode *selector = unparen_expr(se->selector);
|
Ast *selector = unparen_expr(se->selector);
|
||||||
if (selector == nullptr) {
|
if (selector == nullptr) {
|
||||||
operand->mode = Addressing_Invalid;
|
operand->mode = Addressing_Invalid;
|
||||||
operand->expr = node;
|
operand->expr = node;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selector->kind != AstNode_Ident) {
|
if (selector->kind != Ast_Ident) {
|
||||||
// if (selector->kind != AstNode_Ident) {
|
// if (selector->kind != Ast_Ident) {
|
||||||
error(selector, "Illegal selector kind: '%.*s'", LIT(ast_node_strings[selector->kind]));
|
error(selector, "Illegal selector kind: '%.*s'", LIT(ast_strings[selector->kind]));
|
||||||
operand->mode = Addressing_Invalid;
|
operand->mode = Addressing_Invalid;
|
||||||
operand->expr = node;
|
operand->expr = node;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op_expr->kind == AstNode_Ident) {
|
if (op_expr->kind == Ast_Ident) {
|
||||||
String op_name = op_expr->Ident.token.string;
|
String op_name = op_expr->Ident.token.string;
|
||||||
Entity *e = scope_lookup(c->scope, op_name);
|
Entity *e = scope_lookup(c->scope, op_name);
|
||||||
add_entity_use(c, op_expr, e);
|
add_entity_use(c, op_expr, e);
|
||||||
expr_entity = e;
|
expr_entity = e;
|
||||||
|
|
||||||
Entity *original_e = e;
|
Entity *original_e = e;
|
||||||
if (e != nullptr && e->kind == Entity_ImportName && selector->kind == AstNode_Ident) {
|
if (e != nullptr && e->kind == Entity_ImportName && selector->kind == Ast_Ident) {
|
||||||
// IMPORTANT NOTE(bill): This is very sloppy code but it's also very fragile
|
// IMPORTANT NOTE(bill): This is very sloppy code but it's also very fragile
|
||||||
// It pretty much needs to be in this order and this way
|
// It pretty much needs to be in this order and this way
|
||||||
// If you can clean this up, please do but be really careful
|
// If you can clean this up, please do but be really careful
|
||||||
@@ -2659,7 +2659,7 @@ Entity *check_selector(CheckerContext *c, Operand *operand, AstNode *node, Type
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (entity == nullptr && selector->kind == AstNode_Ident) {
|
if (entity == nullptr && selector->kind == Ast_Ident) {
|
||||||
String field_name = selector->Ident.token.string;
|
String field_name = selector->Ident.token.string;
|
||||||
if (is_type_dynamic_array(type_deref(operand->type))) {
|
if (is_type_dynamic_array(type_deref(operand->type))) {
|
||||||
init_mem_allocator(c->checker);
|
init_mem_allocator(c->checker);
|
||||||
@@ -2749,8 +2749,8 @@ Entity *check_selector(CheckerContext *c, Operand *operand, AstNode *node, Type
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_builtin_procedure(CheckerContext *c, Operand *operand, AstNode *call, i32 id) {
|
bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 id) {
|
||||||
GB_ASSERT(call->kind == AstNode_CallExpr);
|
GB_ASSERT(call->kind == Ast_CallExpr);
|
||||||
ast_node(ce, CallExpr, call);
|
ast_node(ce, CallExpr, call);
|
||||||
BuiltinProc *bp = &builtin_procs[id];
|
BuiltinProc *bp = &builtin_procs[id];
|
||||||
{
|
{
|
||||||
@@ -2772,7 +2772,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, AstNode *call,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ce->args.count > 0) {
|
if (ce->args.count > 0) {
|
||||||
if (ce->args[0]->kind == AstNode_FieldValue) {
|
if (ce->args[0]->kind == Ast_FieldValue) {
|
||||||
error(call, "'field = value' calling is not allowed on built-in procedures");
|
error(call, "'field = value' calling is not allowed on built-in procedures");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2816,12 +2816,12 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, AstNode *call,
|
|||||||
error(ce->args[0], "'#location' expects either 0 or 1 arguments, got %td", ce->args.count);
|
error(ce->args[0], "'#location' expects either 0 or 1 arguments, got %td", ce->args.count);
|
||||||
}
|
}
|
||||||
if (ce->args.count > 0) {
|
if (ce->args.count > 0) {
|
||||||
AstNode *arg = ce->args[0];
|
Ast *arg = ce->args[0];
|
||||||
Entity *e = nullptr;
|
Entity *e = nullptr;
|
||||||
Operand o = {};
|
Operand o = {};
|
||||||
if (arg->kind == AstNode_Ident) {
|
if (arg->kind == Ast_Ident) {
|
||||||
e = check_ident(c, &o, arg, nullptr, nullptr, true);
|
e = check_ident(c, &o, arg, nullptr, nullptr, true);
|
||||||
} else if (arg->kind == AstNode_SelectorExpr) {
|
} else if (arg->kind == Ast_SelectorExpr) {
|
||||||
e = check_selector(c, &o, arg, nullptr);
|
e = check_selector(c, &o, arg, nullptr);
|
||||||
}
|
}
|
||||||
if (e == nullptr) {
|
if (e == nullptr) {
|
||||||
@@ -3069,7 +3069,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, AstNode *call,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *capacity = ce->args[1];
|
Ast *capacity = ce->args[1];
|
||||||
Operand op = {};
|
Operand op = {};
|
||||||
check_expr(c, &op, capacity);
|
check_expr(c, &op, capacity);
|
||||||
if (op.mode == Addressing_Invalid) {
|
if (op.mode == Addressing_Invalid) {
|
||||||
@@ -3169,7 +3169,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, AstNode *call,
|
|||||||
|
|
||||||
Type *key = base_type(type)->Map.key;
|
Type *key = base_type(type)->Map.key;
|
||||||
Operand x = {Addressing_Invalid};
|
Operand x = {Addressing_Invalid};
|
||||||
AstNode *key_node = ce->args[1];
|
Ast *key_node = ce->args[1];
|
||||||
Operand op = {};
|
Operand op = {};
|
||||||
check_expr(c, &op, key_node);
|
check_expr(c, &op, key_node);
|
||||||
if (op.mode == Addressing_Invalid) {
|
if (op.mode == Addressing_Invalid) {
|
||||||
@@ -3245,9 +3245,9 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, AstNode *call,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *field_arg = unparen_expr(ce->args[1]);
|
Ast *field_arg = unparen_expr(ce->args[1]);
|
||||||
if (field_arg == nullptr ||
|
if (field_arg == nullptr ||
|
||||||
field_arg->kind != AstNode_Ident) {
|
field_arg->kind != Ast_Ident) {
|
||||||
error(field_arg, "Expected an identifier for field argument");
|
error(field_arg, "Expected an identifier for field argument");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -3284,7 +3284,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, AstNode *call,
|
|||||||
|
|
||||||
case BuiltinProc_type_of: {
|
case BuiltinProc_type_of: {
|
||||||
// proc type_of(val: Type) -> type(Type)
|
// proc type_of(val: Type) -> type(Type)
|
||||||
AstNode *expr = ce->args[0];
|
Ast *expr = ce->args[0];
|
||||||
Operand o = {};
|
Operand o = {};
|
||||||
check_expr_or_type(c, &o, expr);
|
check_expr_or_type(c, &o, expr);
|
||||||
|
|
||||||
@@ -3325,7 +3325,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, AstNode *call,
|
|||||||
|
|
||||||
// NOTE(bill): The type information may not be setup yet
|
// NOTE(bill): The type information may not be setup yet
|
||||||
init_core_type_info(c->checker);
|
init_core_type_info(c->checker);
|
||||||
AstNode *expr = ce->args[0];
|
Ast *expr = ce->args[0];
|
||||||
Operand o = {};
|
Operand o = {};
|
||||||
check_expr_or_type(c, &o, expr);
|
check_expr_or_type(c, &o, expr);
|
||||||
if (o.mode == Addressing_Invalid) {
|
if (o.mode == Addressing_Invalid) {
|
||||||
@@ -3360,7 +3360,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, AstNode *call,
|
|||||||
|
|
||||||
// NOTE(bill): The type information may not be setup yet
|
// NOTE(bill): The type information may not be setup yet
|
||||||
init_core_type_info(c->checker);
|
init_core_type_info(c->checker);
|
||||||
AstNode *expr = ce->args[0];
|
Ast *expr = ce->args[0];
|
||||||
Operand o = {};
|
Operand o = {};
|
||||||
check_expr_or_type(c, &o, expr);
|
check_expr_or_type(c, &o, expr);
|
||||||
if (o.mode == Addressing_Invalid) {
|
if (o.mode == Addressing_Invalid) {
|
||||||
@@ -3408,7 +3408,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, AstNode *call,
|
|||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
AstNode *arg = ce->args[i];
|
Ast *arg = ce->args[i];
|
||||||
Operand op = {};
|
Operand op = {};
|
||||||
check_expr(c, &op, arg);
|
check_expr(c, &op, arg);
|
||||||
if (op.mode == Addressing_Invalid) {
|
if (op.mode == Addressing_Invalid) {
|
||||||
@@ -3672,7 +3672,7 @@ break;
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *other_arg = ce->args[1];
|
Ast *other_arg = ce->args[1];
|
||||||
Operand a = *operand;
|
Operand a = *operand;
|
||||||
Operand b = {};
|
Operand b = {};
|
||||||
check_expr(c, &b, other_arg);
|
check_expr(c, &b, other_arg);
|
||||||
@@ -3749,7 +3749,7 @@ break;
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *other_arg = ce->args[1];
|
Ast *other_arg = ce->args[1];
|
||||||
Operand a = *operand;
|
Operand a = *operand;
|
||||||
Operand b = {};
|
Operand b = {};
|
||||||
check_expr(c, &b, other_arg);
|
check_expr(c, &b, other_arg);
|
||||||
@@ -3871,8 +3871,8 @@ break;
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *min_arg = ce->args[1];
|
Ast *min_arg = ce->args[1];
|
||||||
AstNode *max_arg = ce->args[2];
|
Ast *max_arg = ce->args[2];
|
||||||
Operand x = *operand;
|
Operand x = *operand;
|
||||||
Operand y = {};
|
Operand y = {};
|
||||||
Operand z = {};
|
Operand z = {};
|
||||||
@@ -3972,7 +3972,7 @@ break;
|
|||||||
error(ce->args[0], "Expected a type for 'transmute'");
|
error(ce->args[0], "Expected a type for 'transmute'");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
AstNode *expr = ce->args[1];
|
Ast *expr = ce->args[1];
|
||||||
Operand *o = operand;
|
Operand *o = operand;
|
||||||
check_expr(c, o, expr);
|
check_expr(c, o, expr);
|
||||||
if (o->mode == Addressing_Invalid) {
|
if (o->mode == Addressing_Invalid) {
|
||||||
@@ -4040,7 +4040,7 @@ isize add_dependencies_from_unpacking(CheckerContext *c, Entity **lhs, isize lhs
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count, Array<Operand> *operands, Array<AstNode *> const &rhs, bool allow_ok, bool *optional_ok_ = nullptr) {
|
void check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count, Array<Operand> *operands, Array<Ast *> const &rhs, bool allow_ok, bool *optional_ok_ = nullptr) {
|
||||||
bool optional_ok = false;
|
bool optional_ok = false;
|
||||||
isize tuple_index = 0;
|
isize tuple_index = 0;
|
||||||
for_array(i, rhs) {
|
for_array(i, rhs) {
|
||||||
@@ -4304,13 +4304,13 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_call_expr_field_value(AstNodeCallExpr *ce) {
|
bool is_call_expr_field_value(AstCallExpr *ce) {
|
||||||
GB_ASSERT(ce != nullptr);
|
GB_ASSERT(ce != nullptr);
|
||||||
|
|
||||||
if (ce->args.count == 0) {
|
if (ce->args.count == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return ce->args[0]->kind == AstNode_FieldValue;
|
return ce->args[0]->kind == Ast_FieldValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
isize lookup_procedure_parameter(TypeProc *pt, String parameter_name) {
|
isize lookup_procedure_parameter(TypeProc *pt, String parameter_name) {
|
||||||
@@ -4359,9 +4359,9 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
|||||||
defer (array_free(&ordered_operands));
|
defer (array_free(&ordered_operands));
|
||||||
|
|
||||||
for_array(i, ce->args) {
|
for_array(i, ce->args) {
|
||||||
AstNode *arg = ce->args[i];
|
Ast *arg = ce->args[i];
|
||||||
ast_node(fv, FieldValue, arg);
|
ast_node(fv, FieldValue, arg);
|
||||||
if (fv->field->kind != AstNode_Ident) {
|
if (fv->field->kind != Ast_Ident) {
|
||||||
if (show_error) {
|
if (show_error) {
|
||||||
gbString expr_str = expr_to_string(fv->field);
|
gbString expr_str = expr_to_string(fv->field);
|
||||||
error(arg, "Invalid parameter name '%s' in procedure call", expr_str);
|
error(arg, "Invalid parameter name '%s' in procedure call", expr_str);
|
||||||
@@ -4483,7 +4483,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type *proc_type, AstNode *call) {
|
CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type *proc_type, Ast *call) {
|
||||||
ast_node(ce, CallExpr, call);
|
ast_node(ce, CallExpr, call);
|
||||||
|
|
||||||
CallArgumentCheckerType *call_checker = check_call_arguments_internal;
|
CallArgumentCheckerType *call_checker = check_call_arguments_internal;
|
||||||
@@ -4497,7 +4497,7 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
|
|||||||
|
|
||||||
operands = array_make<Operand>(heap_allocator(), ce->args.count);
|
operands = array_make<Operand>(heap_allocator(), ce->args.count);
|
||||||
for_array(i, ce->args) {
|
for_array(i, ce->args) {
|
||||||
AstNode *arg = ce->args[i];
|
Ast *arg = ce->args[i];
|
||||||
ast_node(fv, FieldValue, arg);
|
ast_node(fv, FieldValue, arg);
|
||||||
check_expr_or_type(c, &operands[i], fv->value);
|
check_expr_or_type(c, &operands[i], fv->value);
|
||||||
}
|
}
|
||||||
@@ -4637,9 +4637,9 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
|
|||||||
}
|
}
|
||||||
result_type = t_invalid;
|
result_type = t_invalid;
|
||||||
} else {
|
} else {
|
||||||
AstNode *ident = operand->expr;
|
Ast *ident = operand->expr;
|
||||||
while (ident->kind == AstNode_SelectorExpr) {
|
while (ident->kind == Ast_SelectorExpr) {
|
||||||
AstNode *s = ident->SelectorExpr.selector;
|
Ast *s = ident->SelectorExpr.selector;
|
||||||
ident = s;
|
ident = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4654,9 +4654,9 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
AstNode *ident = operand->expr;
|
Ast *ident = operand->expr;
|
||||||
while (ident->kind == AstNode_SelectorExpr) {
|
while (ident->kind == Ast_SelectorExpr) {
|
||||||
AstNode *s = ident->SelectorExpr.selector;
|
Ast *s = ident->SelectorExpr.selector;
|
||||||
ident = s;
|
ident = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4694,7 +4694,7 @@ isize lookup_polymorphic_struct_parameter(TypeStruct *st, String parameter_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CallArgumentError check_polymorphic_struct_type(CheckerContext *c, Operand *operand, AstNode *call) {
|
CallArgumentError check_polymorphic_struct_type(CheckerContext *c, Operand *operand, Ast *call) {
|
||||||
ast_node(ce, CallExpr, call);
|
ast_node(ce, CallExpr, call);
|
||||||
|
|
||||||
Type *original_type = operand->type;
|
Type *original_type = operand->type;
|
||||||
@@ -4714,7 +4714,7 @@ CallArgumentError check_polymorphic_struct_type(CheckerContext *c, Operand *oper
|
|||||||
named_fields = true;
|
named_fields = true;
|
||||||
operands = array_make<Operand>(heap_allocator(), ce->args.count);
|
operands = array_make<Operand>(heap_allocator(), ce->args.count);
|
||||||
for_array(i, ce->args) {
|
for_array(i, ce->args) {
|
||||||
AstNode *arg = ce->args[i];
|
Ast *arg = ce->args[i];
|
||||||
ast_node(fv, FieldValue, arg);
|
ast_node(fv, FieldValue, arg);
|
||||||
check_expr_or_type(c, &operands[i], fv->value);
|
check_expr_or_type(c, &operands[i], fv->value);
|
||||||
}
|
}
|
||||||
@@ -4742,9 +4742,9 @@ CallArgumentError check_polymorphic_struct_type(CheckerContext *c, Operand *oper
|
|||||||
ordered_operands = array_make<Operand>(c->allocator, param_count);
|
ordered_operands = array_make<Operand>(c->allocator, param_count);
|
||||||
|
|
||||||
for_array(i, ce->args) {
|
for_array(i, ce->args) {
|
||||||
AstNode *arg = ce->args[i];
|
Ast *arg = ce->args[i];
|
||||||
ast_node(fv, FieldValue, arg);
|
ast_node(fv, FieldValue, arg);
|
||||||
if (fv->field->kind != AstNode_Ident) {
|
if (fv->field->kind != Ast_Ident) {
|
||||||
if (show_error) {
|
if (show_error) {
|
||||||
gbString expr_str = expr_to_string(fv->field);
|
gbString expr_str = expr_to_string(fv->field);
|
||||||
error(arg, "Invalid parameter name '%s' in polymorphic type call", expr_str);
|
error(arg, "Invalid parameter name '%s' in polymorphic type call", expr_str);
|
||||||
@@ -4867,7 +4867,7 @@ CallArgumentError check_polymorphic_struct_type(CheckerContext *c, Operand *oper
|
|||||||
String generated_name = make_string_c(expr_to_string(call));
|
String generated_name = make_string_c(expr_to_string(call));
|
||||||
|
|
||||||
Type *named_type = alloc_type_named(generated_name, nullptr, nullptr);
|
Type *named_type = alloc_type_named(generated_name, nullptr, nullptr);
|
||||||
AstNode *node = clone_ast_node(a, st->node);
|
Ast *node = clone_ast_node(a, st->node);
|
||||||
Type *struct_type = alloc_type_struct();
|
Type *struct_type = alloc_type_struct();
|
||||||
struct_type->Struct.node = node;
|
struct_type->Struct.node = node;
|
||||||
struct_type->Struct.polymorphic_parent = original_type;
|
struct_type->Struct.polymorphic_parent = original_type;
|
||||||
@@ -4884,10 +4884,10 @@ CallArgumentError check_polymorphic_struct_type(CheckerContext *c, Operand *oper
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ExprKind check_call_expr(CheckerContext *c, Operand *operand, AstNode *call) {
|
ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call) {
|
||||||
ast_node(ce, CallExpr, call);
|
ast_node(ce, CallExpr, call);
|
||||||
if (ce->proc != nullptr &&
|
if (ce->proc != nullptr &&
|
||||||
ce->proc->kind == AstNode_BasicDirective) {
|
ce->proc->kind == Ast_BasicDirective) {
|
||||||
ast_node(bd, BasicDirective, ce->proc);
|
ast_node(bd, BasicDirective, ce->proc);
|
||||||
String name = bd->name;
|
String name = bd->name;
|
||||||
if (name == "location" || name == "assert") {
|
if (name == "location" || name == "assert") {
|
||||||
@@ -4905,14 +4905,14 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, AstNode *call) {
|
|||||||
|
|
||||||
if (ce->args.count > 0) {
|
if (ce->args.count > 0) {
|
||||||
bool fail = false;
|
bool fail = false;
|
||||||
bool first_is_field_value = (ce->args[0]->kind == AstNode_FieldValue);
|
bool first_is_field_value = (ce->args[0]->kind == Ast_FieldValue);
|
||||||
for_array(i, ce->args) {
|
for_array(i, ce->args) {
|
||||||
AstNode *arg = ce->args[i];
|
Ast *arg = ce->args[i];
|
||||||
bool mix = false;
|
bool mix = false;
|
||||||
if (first_is_field_value) {
|
if (first_is_field_value) {
|
||||||
mix = arg->kind != AstNode_FieldValue;
|
mix = arg->kind != Ast_FieldValue;
|
||||||
} else {
|
} else {
|
||||||
mix = arg->kind == AstNode_FieldValue;
|
mix = arg->kind == Ast_FieldValue;
|
||||||
}
|
}
|
||||||
if (mix) {
|
if (mix) {
|
||||||
error(arg, "Mixture of 'field = value' and value elements in a procedure all is not allowed");
|
error(arg, "Mixture of 'field = value' and value elements in a procedure all is not allowed");
|
||||||
@@ -4929,8 +4929,8 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, AstNode *call) {
|
|||||||
|
|
||||||
if (operand->mode == Addressing_Invalid) {
|
if (operand->mode == Addressing_Invalid) {
|
||||||
for_array(i, ce->args) {
|
for_array(i, ce->args) {
|
||||||
AstNode *arg = ce->args[i];
|
Ast *arg = ce->args[i];
|
||||||
if (arg->kind == AstNode_FieldValue) {
|
if (arg->kind == Ast_FieldValue) {
|
||||||
arg = arg->FieldValue.value;
|
arg = arg->FieldValue.value;
|
||||||
}
|
}
|
||||||
check_expr_base(c, operand, arg, nullptr);
|
check_expr_base(c, operand, arg, nullptr);
|
||||||
@@ -4945,9 +4945,9 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, AstNode *call) {
|
|||||||
if (is_type_polymorphic_struct(t)) {
|
if (is_type_polymorphic_struct(t)) {
|
||||||
auto err = check_polymorphic_struct_type(c, operand, call);
|
auto err = check_polymorphic_struct_type(c, operand, call);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
AstNode *ident = operand->expr;
|
Ast *ident = operand->expr;
|
||||||
while (ident->kind == AstNode_SelectorExpr) {
|
while (ident->kind == Ast_SelectorExpr) {
|
||||||
AstNode *s = ident->SelectorExpr.selector;
|
Ast *s = ident->SelectorExpr.selector;
|
||||||
ident = s;
|
ident = s;
|
||||||
}
|
}
|
||||||
Type *ot = operand->type; GB_ASSERT(ot->kind == Type_Named);
|
Type *ot = operand->type; GB_ASSERT(ot->kind == Type_Named);
|
||||||
@@ -4968,8 +4968,8 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, AstNode *call) {
|
|||||||
case 0: error(call, "Missing argument in conversion to '%s'", str); break;
|
case 0: error(call, "Missing argument in conversion to '%s'", str); break;
|
||||||
default: error(call, "Too many arguments in conversion to '%s'", str); break;
|
default: error(call, "Too many arguments in conversion to '%s'", str); break;
|
||||||
case 1: {
|
case 1: {
|
||||||
AstNode *arg = ce->args[0];
|
Ast *arg = ce->args[0];
|
||||||
if (arg->kind == AstNode_FieldValue) {
|
if (arg->kind == Ast_FieldValue) {
|
||||||
error(call, "'field = value' cannot be used in a type conversion");
|
error(call, "'field = value' cannot be used in a type conversion");
|
||||||
arg = arg->FieldValue.value;
|
arg = arg->FieldValue.value;
|
||||||
// NOTE(bill): Carry on the cast regardless
|
// NOTE(bill): Carry on the cast regardless
|
||||||
@@ -5000,7 +5000,7 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, AstNode *call) {
|
|||||||
bool valid_type = (proc_type != nullptr) && is_type_proc(proc_type);
|
bool valid_type = (proc_type != nullptr) && is_type_proc(proc_type);
|
||||||
bool valid_mode = is_operand_value(*operand);
|
bool valid_mode = is_operand_value(*operand);
|
||||||
if (!valid_type || !valid_mode) {
|
if (!valid_type || !valid_mode) {
|
||||||
AstNode *e = operand->expr;
|
Ast *e = operand->expr;
|
||||||
gbString str = expr_to_string(e);
|
gbString str = expr_to_string(e);
|
||||||
gbString type_str = type_to_string(operand->type);
|
gbString type_str = type_to_string(operand->type);
|
||||||
error(e, "Cannot call a non-procedure: '%s' of type '%s'", str, type_str);
|
error(e, "Cannot call a non-procedure: '%s' of type '%s'", str, type_str);
|
||||||
@@ -5061,7 +5061,7 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, AstNode *call) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_expr_with_type_hint(CheckerContext *c, Operand *o, AstNode *e, Type *t) {
|
void check_expr_with_type_hint(CheckerContext *c, Operand *o, Ast *e, Type *t) {
|
||||||
check_expr_base(c, o, e, t);
|
check_expr_base(c, o, e, t);
|
||||||
check_not_tuple(c, o);
|
check_not_tuple(c, o);
|
||||||
char *err_str = nullptr;
|
char *err_str = nullptr;
|
||||||
@@ -5145,7 +5145,7 @@ bool ternary_compare_types(Type *x, Type *y) {
|
|||||||
return are_types_identical(x, y);
|
return are_types_identical(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, AstNode *node, Type *type_hint) {
|
ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
|
||||||
ExprKind kind = Expr_Stmt;
|
ExprKind kind = Expr_Stmt;
|
||||||
|
|
||||||
o->mode = Addressing_Invalid;
|
o->mode = Addressing_Invalid;
|
||||||
@@ -5387,9 +5387,9 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, AstNode *node,
|
|||||||
type = nullptr;
|
type = nullptr;
|
||||||
|
|
||||||
// [?]Type
|
// [?]Type
|
||||||
if (cl->type->kind == AstNode_ArrayType && cl->type->ArrayType.count != nullptr) {
|
if (cl->type->kind == Ast_ArrayType && cl->type->ArrayType.count != nullptr) {
|
||||||
AstNode *count = cl->type->ArrayType.count;
|
Ast *count = cl->type->ArrayType.count;
|
||||||
if (count->kind == AstNode_UnaryExpr &&
|
if (count->kind == Ast_UnaryExpr &&
|
||||||
count->UnaryExpr.op.kind == Token_Question) {
|
count->UnaryExpr.op.kind == Token_Question) {
|
||||||
type = alloc_type_array(check_type(c, cl->type->ArrayType.elem), -1);
|
type = alloc_type_array(check_type(c, cl->type->ArrayType.elem), -1);
|
||||||
is_to_be_determined_array_count = true;
|
is_to_be_determined_array_count = true;
|
||||||
@@ -5452,17 +5452,17 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, AstNode *node,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cl->elems[0]->kind == AstNode_FieldValue) {
|
if (cl->elems[0]->kind == Ast_FieldValue) {
|
||||||
bool *fields_visited = gb_alloc_array(c->allocator, bool, field_count);
|
bool *fields_visited = gb_alloc_array(c->allocator, bool, field_count);
|
||||||
|
|
||||||
for_array(i, cl->elems) {
|
for_array(i, cl->elems) {
|
||||||
AstNode *elem = cl->elems[i];
|
Ast *elem = cl->elems[i];
|
||||||
if (elem->kind != AstNode_FieldValue) {
|
if (elem->kind != Ast_FieldValue) {
|
||||||
error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed");
|
error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ast_node(fv, FieldValue, elem);
|
ast_node(fv, FieldValue, elem);
|
||||||
if (fv->field->kind != AstNode_Ident) {
|
if (fv->field->kind != Ast_Ident) {
|
||||||
gbString expr_str = expr_to_string(fv->field);
|
gbString expr_str = expr_to_string(fv->field);
|
||||||
error(elem, "Invalid field name '%s' in structure literal", expr_str);
|
error(elem, "Invalid field name '%s' in structure literal", expr_str);
|
||||||
gb_string_free(expr_str);
|
gb_string_free(expr_str);
|
||||||
@@ -5508,8 +5508,8 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, AstNode *node,
|
|||||||
|
|
||||||
for_array(index, cl->elems) {
|
for_array(index, cl->elems) {
|
||||||
Entity *field = nullptr;
|
Entity *field = nullptr;
|
||||||
AstNode *elem = cl->elems[index];
|
Ast *elem = cl->elems[index];
|
||||||
if (elem->kind == AstNode_FieldValue) {
|
if (elem->kind == Ast_FieldValue) {
|
||||||
seen_field_value = true;
|
seen_field_value = true;
|
||||||
// error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed");
|
// error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed");
|
||||||
// continue;
|
// continue;
|
||||||
@@ -5592,13 +5592,13 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, AstNode *node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (; index < cl->elems.count; index++) {
|
for (; index < cl->elems.count; index++) {
|
||||||
AstNode *e = cl->elems[index];
|
Ast *e = cl->elems[index];
|
||||||
if (e == nullptr) {
|
if (e == nullptr) {
|
||||||
error(node, "Invalid literal element");
|
error(node, "Invalid literal element");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e->kind == AstNode_FieldValue) {
|
if (e->kind == Ast_FieldValue) {
|
||||||
error(e, "'field = value' is only allowed in struct literals");
|
error(e, "'field = value' is only allowed in struct literals");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -5640,17 +5640,17 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, AstNode *node,
|
|||||||
{ // Checker values
|
{ // Checker values
|
||||||
Type *field_types[2] = {t_rawptr, t_typeid};
|
Type *field_types[2] = {t_rawptr, t_typeid};
|
||||||
isize field_count = 2;
|
isize field_count = 2;
|
||||||
if (cl->elems[0]->kind == AstNode_FieldValue) {
|
if (cl->elems[0]->kind == Ast_FieldValue) {
|
||||||
bool fields_visited[2] = {};
|
bool fields_visited[2] = {};
|
||||||
|
|
||||||
for_array(i, cl->elems) {
|
for_array(i, cl->elems) {
|
||||||
AstNode *elem = cl->elems[i];
|
Ast *elem = cl->elems[i];
|
||||||
if (elem->kind != AstNode_FieldValue) {
|
if (elem->kind != Ast_FieldValue) {
|
||||||
error(elem, "Mixture of 'field = value' and value elements in a 'any' literal is not allowed");
|
error(elem, "Mixture of 'field = value' and value elements in a 'any' literal is not allowed");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ast_node(fv, FieldValue, elem);
|
ast_node(fv, FieldValue, elem);
|
||||||
if (fv->field->kind != AstNode_Ident) {
|
if (fv->field->kind != Ast_Ident) {
|
||||||
gbString expr_str = expr_to_string(fv->field);
|
gbString expr_str = expr_to_string(fv->field);
|
||||||
error(elem, "Invalid field name '%s' in 'any' literal", expr_str);
|
error(elem, "Invalid field name '%s' in 'any' literal", expr_str);
|
||||||
gb_string_free(expr_str);
|
gb_string_free(expr_str);
|
||||||
@@ -5681,8 +5681,8 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, AstNode *node,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for_array(index, cl->elems) {
|
for_array(index, cl->elems) {
|
||||||
AstNode *elem = cl->elems[index];
|
Ast *elem = cl->elems[index];
|
||||||
if (elem->kind == AstNode_FieldValue) {
|
if (elem->kind == Ast_FieldValue) {
|
||||||
error(elem, "Mixture of 'field = value' and value elements in a 'any' literal is not allowed");
|
error(elem, "Mixture of 'field = value' and value elements in a 'any' literal is not allowed");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -5715,8 +5715,8 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, AstNode *node,
|
|||||||
is_constant = false;
|
is_constant = false;
|
||||||
{ // Checker values
|
{ // Checker values
|
||||||
for_array(i, cl->elems) {
|
for_array(i, cl->elems) {
|
||||||
AstNode *elem = cl->elems[i];
|
Ast *elem = cl->elems[i];
|
||||||
if (elem->kind != AstNode_FieldValue) {
|
if (elem->kind != Ast_FieldValue) {
|
||||||
error(elem, "Only 'field = value' elements are allowed in a map literal");
|
error(elem, "Only 'field = value' elements are allowed in a map literal");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -6067,7 +6067,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, AstNode *node,
|
|||||||
TokenKind interval_kind = se->interval.kind;
|
TokenKind interval_kind = se->interval.kind;
|
||||||
|
|
||||||
i64 indices[2] = {};
|
i64 indices[2] = {};
|
||||||
AstNode *nodes[2] = {se->low, se->high};
|
Ast *nodes[2] = {se->low, se->high};
|
||||||
for (isize i = 0; i < gb_count_of(nodes); i++) {
|
for (isize i = 0; i < gb_count_of(nodes); i++) {
|
||||||
i64 index = max_count;
|
i64 index = max_count;
|
||||||
if (nodes[i] != nullptr) {
|
if (nodes[i] != nullptr) {
|
||||||
@@ -6128,17 +6128,17 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, AstNode *node,
|
|||||||
}
|
}
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case AstNode_TypeType:
|
case Ast_TypeType:
|
||||||
case AstNode_PolyType:
|
case Ast_PolyType:
|
||||||
case AstNode_ProcType:
|
case Ast_ProcType:
|
||||||
case AstNode_PointerType:
|
case Ast_PointerType:
|
||||||
case AstNode_ArrayType:
|
case Ast_ArrayType:
|
||||||
case AstNode_DynamicArrayType:
|
case Ast_DynamicArrayType:
|
||||||
case AstNode_StructType:
|
case Ast_StructType:
|
||||||
case AstNode_UnionType:
|
case Ast_UnionType:
|
||||||
// case AstNode_RawUnionType:
|
// case Ast_RawUnionType:
|
||||||
case AstNode_EnumType:
|
case Ast_EnumType:
|
||||||
case AstNode_MapType:
|
case Ast_MapType:
|
||||||
o->mode = Addressing_Type;
|
o->mode = Addressing_Type;
|
||||||
o->type = check_type(c, node);
|
o->type = check_type(c, node);
|
||||||
break;
|
break;
|
||||||
@@ -6149,7 +6149,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, AstNode *node,
|
|||||||
return kind;
|
return kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprKind check_expr_base(CheckerContext *c, Operand *o, AstNode *node, Type *type_hint) {
|
ExprKind check_expr_base(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
|
||||||
ExprKind kind = check_expr_base_internal(c, o, node, type_hint);
|
ExprKind kind = check_expr_base_internal(c, o, node, type_hint);
|
||||||
Type *type = nullptr;
|
Type *type = nullptr;
|
||||||
ExactValue value = {ExactValue_Invalid};
|
ExactValue value = {ExactValue_Invalid};
|
||||||
@@ -6179,7 +6179,7 @@ ExprKind check_expr_base(CheckerContext *c, Operand *o, AstNode *node, Type *typ
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void check_multi_expr(CheckerContext *c, Operand *o, AstNode *e) {
|
void check_multi_expr(CheckerContext *c, Operand *o, Ast *e) {
|
||||||
check_expr_base(c, o, e, nullptr);
|
check_expr_base(c, o, e, nullptr);
|
||||||
switch (o->mode) {
|
switch (o->mode) {
|
||||||
default:
|
default:
|
||||||
@@ -6207,22 +6207,22 @@ void check_not_tuple(CheckerContext *c, Operand *o) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_expr(CheckerContext *c, Operand *o, AstNode *e) {
|
void check_expr(CheckerContext *c, Operand *o, Ast *e) {
|
||||||
check_multi_expr(c, o, e);
|
check_multi_expr(c, o, e);
|
||||||
check_not_tuple(c, o);
|
check_not_tuple(c, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_expr_or_type(CheckerContext *c, Operand *o, AstNode *e, Type *type_hint) {
|
void check_expr_or_type(CheckerContext *c, Operand *o, Ast *e, Type *type_hint) {
|
||||||
check_expr_base(c, o, e, type_hint);
|
check_expr_base(c, o, e, type_hint);
|
||||||
check_not_tuple(c, o);
|
check_not_tuple(c, o);
|
||||||
error_operand_no_value(o);
|
error_operand_no_value(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gbString write_expr_to_string(gbString str, AstNode *node);
|
gbString write_expr_to_string(gbString str, Ast *node);
|
||||||
|
|
||||||
gbString write_struct_fields_to_string(gbString str, Array<AstNode *> const ¶ms) {
|
gbString write_struct_fields_to_string(gbString str, Array<Ast *> const ¶ms) {
|
||||||
for_array(i, params) {
|
for_array(i, params) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
str = gb_string_appendc(str, ", ");
|
str = gb_string_appendc(str, ", ");
|
||||||
@@ -6245,11 +6245,11 @@ gbString string_append_token(gbString str, Token token) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gbString write_expr_to_string(gbString str, AstNode *node) {
|
gbString write_expr_to_string(gbString str, Ast *node) {
|
||||||
if (node == nullptr)
|
if (node == nullptr)
|
||||||
return str;
|
return str;
|
||||||
|
|
||||||
if (is_ast_node_stmt(node)) {
|
if (is_ast_stmt(node)) {
|
||||||
GB_ASSERT("stmt passed to write_expr_to_string");
|
GB_ASSERT("stmt passed to write_expr_to_string");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6423,7 +6423,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
case_ast_node(at, ArrayType, node);
|
case_ast_node(at, ArrayType, node);
|
||||||
str = gb_string_append_rune(str, '[');
|
str = gb_string_append_rune(str, '[');
|
||||||
if (at->count != nullptr &&
|
if (at->count != nullptr &&
|
||||||
at->count->kind == AstNode_UnaryExpr &&
|
at->count->kind == Ast_UnaryExpr &&
|
||||||
at->count->UnaryExpr.op.kind == Token_Question) {
|
at->count->UnaryExpr.op.kind == Token_Question) {
|
||||||
str = gb_string_appendc(str, "?");
|
str = gb_string_appendc(str, "?");
|
||||||
} else {
|
} else {
|
||||||
@@ -6457,7 +6457,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for_array(i, f->names) {
|
for_array(i, f->names) {
|
||||||
AstNode *name = f->names[i];
|
Ast *name = f->names[i];
|
||||||
if (i > 0) str = gb_string_appendc(str, ", ");
|
if (i > 0) str = gb_string_appendc(str, ", ");
|
||||||
str = write_expr_to_string(str, name);
|
str = write_expr_to_string(str, name);
|
||||||
}
|
}
|
||||||
@@ -6533,7 +6533,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
str = gb_string_appendc(str, "(");
|
str = gb_string_appendc(str, "(");
|
||||||
|
|
||||||
for_array(i, ce->args) {
|
for_array(i, ce->args) {
|
||||||
AstNode *arg = ce->args[i];
|
Ast *arg = ce->args[i];
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
str = gb_string_appendc(str, ", ");
|
str = gb_string_appendc(str, ", ");
|
||||||
}
|
}
|
||||||
@@ -6598,6 +6598,6 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
gbString expr_to_string(AstNode *expression) {
|
gbString expr_to_string(Ast *expression) {
|
||||||
return write_expr_to_string(gb_string_make(heap_allocator(), ""), expression);
|
return write_expr_to_string(gb_string_make(heap_allocator(), ""), expression);
|
||||||
}
|
}
|
||||||
|
|||||||
+95
-95
@@ -1,4 +1,4 @@
|
|||||||
void check_stmt_list(CheckerContext *ctx, Array<AstNode *> const &stmts, u32 flags) {
|
void check_stmt_list(CheckerContext *ctx, Array<Ast *> const &stmts, u32 flags) {
|
||||||
if (stmts.count == 0) {
|
if (stmts.count == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -12,14 +12,14 @@ void check_stmt_list(CheckerContext *ctx, Array<AstNode *> const &stmts, u32 fla
|
|||||||
|
|
||||||
isize max = stmts.count;
|
isize max = stmts.count;
|
||||||
for (isize i = stmts.count-1; i >= 0; i--) {
|
for (isize i = stmts.count-1; i >= 0; i--) {
|
||||||
if (stmts[i]->kind != AstNode_EmptyStmt) {
|
if (stmts[i]->kind != Ast_EmptyStmt) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
max--;
|
max--;
|
||||||
}
|
}
|
||||||
for (isize i = 0; i < max; i++) {
|
for (isize i = 0; i < max; i++) {
|
||||||
AstNode *n = stmts[i];
|
Ast *n = stmts[i];
|
||||||
if (n->kind == AstNode_EmptyStmt) {
|
if (n->kind == Ast_EmptyStmt) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
u32 new_flags = flags;
|
u32 new_flags = flags;
|
||||||
@@ -29,11 +29,11 @@ void check_stmt_list(CheckerContext *ctx, Array<AstNode *> const &stmts, u32 fla
|
|||||||
|
|
||||||
if (i+1 < max) {
|
if (i+1 < max) {
|
||||||
switch (n->kind) {
|
switch (n->kind) {
|
||||||
case AstNode_ReturnStmt:
|
case Ast_ReturnStmt:
|
||||||
error(n, "Statements after this 'return' are never execu");
|
error(n, "Statements after this 'return' are never execu");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AstNode_BranchStmt:
|
case Ast_BranchStmt:
|
||||||
error(n, "Statements after this '%.*s' are never executed", LIT(n->BranchStmt.token.string));
|
error(n, "Statements after this '%.*s' are never executed", LIT(n->BranchStmt.token.string));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -43,11 +43,11 @@ void check_stmt_list(CheckerContext *ctx, Array<AstNode *> const &stmts, u32 fla
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_is_terminating_list(Array<AstNode *> const &stmts) {
|
bool check_is_terminating_list(Array<Ast *> const &stmts) {
|
||||||
// Iterate backwards
|
// Iterate backwards
|
||||||
for (isize n = stmts.count-1; n >= 0; n--) {
|
for (isize n = stmts.count-1; n >= 0; n--) {
|
||||||
AstNode *stmt = stmts[n];
|
Ast *stmt = stmts[n];
|
||||||
if (stmt->kind != AstNode_EmptyStmt) {
|
if (stmt->kind != Ast_EmptyStmt) {
|
||||||
return check_is_terminating(stmt);
|
return check_is_terminating(stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,9 +55,9 @@ bool check_is_terminating_list(Array<AstNode *> const &stmts) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_has_break_list(Array<AstNode *> const &stmts, bool implicit) {
|
bool check_has_break_list(Array<Ast *> const &stmts, bool implicit) {
|
||||||
for_array(i, stmts) {
|
for_array(i, stmts) {
|
||||||
AstNode *stmt = stmts[i];
|
Ast *stmt = stmts[i];
|
||||||
if (check_has_break(stmt, implicit)) {
|
if (check_has_break(stmt, implicit)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -66,24 +66,24 @@ bool check_has_break_list(Array<AstNode *> const &stmts, bool implicit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool check_has_break(AstNode *stmt, bool implicit) {
|
bool check_has_break(Ast *stmt, bool implicit) {
|
||||||
switch (stmt->kind) {
|
switch (stmt->kind) {
|
||||||
case AstNode_BranchStmt:
|
case Ast_BranchStmt:
|
||||||
if (stmt->BranchStmt.token.kind == Token_break) {
|
if (stmt->BranchStmt.token.kind == Token_break) {
|
||||||
return implicit;
|
return implicit;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AstNode_BlockStmt:
|
case Ast_BlockStmt:
|
||||||
return check_has_break_list(stmt->BlockStmt.stmts, implicit);
|
return check_has_break_list(stmt->BlockStmt.stmts, implicit);
|
||||||
|
|
||||||
case AstNode_IfStmt:
|
case Ast_IfStmt:
|
||||||
if (check_has_break(stmt->IfStmt.body, implicit) ||
|
if (check_has_break(stmt->IfStmt.body, implicit) ||
|
||||||
(stmt->IfStmt.else_stmt != nullptr && check_has_break(stmt->IfStmt.else_stmt, implicit))) {
|
(stmt->IfStmt.else_stmt != nullptr && check_has_break(stmt->IfStmt.else_stmt, implicit))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AstNode_CaseClause:
|
case Ast_CaseClause:
|
||||||
return check_has_break_list(stmt->CaseClause.stmts, implicit);
|
return check_has_break_list(stmt->CaseClause.stmts, implicit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ bool check_has_break(AstNode *stmt, bool implicit) {
|
|||||||
|
|
||||||
// NOTE(bill): The last expression has to be a 'return' statement
|
// NOTE(bill): The last expression has to be a 'return' statement
|
||||||
// TODO(bill): This is a mild hack and should be probably handled properly
|
// TODO(bill): This is a mild hack and should be probably handled properly
|
||||||
bool check_is_terminating(AstNode *node) {
|
bool check_is_terminating(Ast *node) {
|
||||||
switch (node->kind) {
|
switch (node->kind) {
|
||||||
case_ast_node(rs, ReturnStmt, node);
|
case_ast_node(rs, ReturnStmt, node);
|
||||||
return true;
|
return true;
|
||||||
@@ -139,7 +139,7 @@ bool check_is_terminating(AstNode *node) {
|
|||||||
case_ast_node(ss, SwitchStmt, node);
|
case_ast_node(ss, SwitchStmt, node);
|
||||||
bool has_default = false;
|
bool has_default = false;
|
||||||
for_array(i, ss->body->BlockStmt.stmts) {
|
for_array(i, ss->body->BlockStmt.stmts) {
|
||||||
AstNode *clause = ss->body->BlockStmt.stmts[i];
|
Ast *clause = ss->body->BlockStmt.stmts[i];
|
||||||
ast_node(cc, CaseClause, clause);
|
ast_node(cc, CaseClause, clause);
|
||||||
if (cc->list.count == 0) {
|
if (cc->list.count == 0) {
|
||||||
has_default = true;
|
has_default = true;
|
||||||
@@ -155,7 +155,7 @@ bool check_is_terminating(AstNode *node) {
|
|||||||
case_ast_node(ss, TypeSwitchStmt, node);
|
case_ast_node(ss, TypeSwitchStmt, node);
|
||||||
bool has_default = false;
|
bool has_default = false;
|
||||||
for_array(i, ss->body->BlockStmt.stmts) {
|
for_array(i, ss->body->BlockStmt.stmts) {
|
||||||
AstNode *clause = ss->body->BlockStmt.stmts[i];
|
Ast *clause = ss->body->BlockStmt.stmts[i];
|
||||||
ast_node(cc, CaseClause, clause);
|
ast_node(cc, CaseClause, clause);
|
||||||
if (cc->list.count == 0) {
|
if (cc->list.count == 0) {
|
||||||
has_default = true;
|
has_default = true;
|
||||||
@@ -186,7 +186,7 @@ Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *node = unparen_expr(lhs->expr);
|
Ast *node = unparen_expr(lhs->expr);
|
||||||
|
|
||||||
// NOTE(bill): Ignore assignments to '_'
|
// NOTE(bill): Ignore assignments to '_'
|
||||||
if (is_blank_ident(node)) {
|
if (is_blank_ident(node)) {
|
||||||
@@ -234,7 +234,7 @@ Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs)
|
|||||||
rhs->proc_group = nullptr;
|
rhs->proc_group = nullptr;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (node->kind == AstNode_Ident) {
|
if (node->kind == Ast_Ident) {
|
||||||
ast_node(i, Ident, node);
|
ast_node(i, Ident, node);
|
||||||
e = scope_lookup(ctx->scope, i->token.string);
|
e = scope_lookup(ctx->scope, i->token.string);
|
||||||
if (e != nullptr && e->kind == Entity_Variable) {
|
if (e != nullptr && e->kind == Entity_Variable) {
|
||||||
@@ -289,9 +289,9 @@ Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case Addressing_MapIndex: {
|
case Addressing_MapIndex: {
|
||||||
AstNode *ln = unparen_expr(lhs->expr);
|
Ast *ln = unparen_expr(lhs->expr);
|
||||||
if (ln->kind == AstNode_IndexExpr) {
|
if (ln->kind == Ast_IndexExpr) {
|
||||||
AstNode *x = ln->IndexExpr.expr;
|
Ast *x = ln->IndexExpr.expr;
|
||||||
TypeAndValue tav = type_and_value_of_expr(&ctx->checker->info, x);
|
TypeAndValue tav = type_and_value_of_expr(&ctx->checker->info, x);
|
||||||
GB_ASSERT(tav.mode != Addressing_Invalid);
|
GB_ASSERT(tav.mode != Addressing_Invalid);
|
||||||
if (tav.mode != Addressing_Variable) {
|
if (tav.mode != Addressing_Variable) {
|
||||||
@@ -308,7 +308,7 @@ Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
if (lhs->expr->kind == AstNode_SelectorExpr) {
|
if (lhs->expr->kind == Ast_SelectorExpr) {
|
||||||
// NOTE(bill): Extra error checks
|
// NOTE(bill): Extra error checks
|
||||||
Operand op_c = {Addressing_Invalid};
|
Operand op_c = {Addressing_Invalid};
|
||||||
ast_node(se, SelectorExpr, lhs->expr);
|
ast_node(se, SelectorExpr, lhs->expr);
|
||||||
@@ -342,8 +342,8 @@ Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags);
|
void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags);
|
||||||
void check_stmt(CheckerContext *ctx, AstNode *node, u32 flags) {
|
void check_stmt(CheckerContext *ctx, Ast *node, u32 flags) {
|
||||||
u32 prev_stmt_state_flags = ctx->stmt_state_flags;
|
u32 prev_stmt_state_flags = ctx->stmt_state_flags;
|
||||||
|
|
||||||
if (node->stmt_state_flags != 0) {
|
if (node->stmt_state_flags != 0) {
|
||||||
@@ -368,14 +368,14 @@ void check_stmt(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_when_stmt(CheckerContext *ctx, AstNodeWhenStmt *ws, u32 flags) {
|
void check_when_stmt(CheckerContext *ctx, AstWhenStmt *ws, u32 flags) {
|
||||||
Operand operand = {Addressing_Invalid};
|
Operand operand = {Addressing_Invalid};
|
||||||
check_expr(ctx, &operand, ws->cond);
|
check_expr(ctx, &operand, ws->cond);
|
||||||
if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) {
|
if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) {
|
||||||
error(ws->cond, "Non-constant boolean 'when' condition");
|
error(ws->cond, "Non-constant boolean 'when' condition");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ws->body == nullptr || ws->body->kind != AstNode_BlockStmt) {
|
if (ws->body == nullptr || ws->body->kind != Ast_BlockStmt) {
|
||||||
error(ws->cond, "Invalid body for 'when' statement");
|
error(ws->cond, "Invalid body for 'when' statement");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -384,10 +384,10 @@ void check_when_stmt(CheckerContext *ctx, AstNodeWhenStmt *ws, u32 flags) {
|
|||||||
check_stmt_list(ctx, ws->body->BlockStmt.stmts, flags);
|
check_stmt_list(ctx, ws->body->BlockStmt.stmts, flags);
|
||||||
} else if (ws->else_stmt) {
|
} else if (ws->else_stmt) {
|
||||||
switch (ws->else_stmt->kind) {
|
switch (ws->else_stmt->kind) {
|
||||||
case AstNode_BlockStmt:
|
case Ast_BlockStmt:
|
||||||
check_stmt_list(ctx, ws->else_stmt->BlockStmt.stmts, flags);
|
check_stmt_list(ctx, ws->else_stmt->BlockStmt.stmts, flags);
|
||||||
break;
|
break;
|
||||||
case AstNode_WhenStmt:
|
case Ast_WhenStmt:
|
||||||
check_when_stmt(ctx, &ws->else_stmt->WhenStmt, flags);
|
check_when_stmt(ctx, &ws->else_stmt->WhenStmt, flags);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -397,12 +397,12 @@ void check_when_stmt(CheckerContext *ctx, AstNodeWhenStmt *ws, u32 flags) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_label(CheckerContext *ctx, AstNode *label) {
|
void check_label(CheckerContext *ctx, Ast *label) {
|
||||||
if (label == nullptr) {
|
if (label == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ast_node(l, Label, label);
|
ast_node(l, Label, label);
|
||||||
if (l->name->kind != AstNode_Ident) {
|
if (l->name->kind != Ast_Ident) {
|
||||||
error(l->name, "A label's name must be an identifier");
|
error(l->name, "A label's name must be an identifier");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -440,7 +440,7 @@ void check_label(CheckerContext *ctx, AstNode *label) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns 'true' for 'continue', 'false' for 'return'
|
// Returns 'true' for 'continue', 'false' for 'return'
|
||||||
bool check_using_stmt_entity(CheckerContext *ctx, AstNodeUsingStmt *us, AstNode *expr, bool is_selector, Entity *e) {
|
bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, Ast *expr, bool is_selector, Entity *e) {
|
||||||
if (e == nullptr) {
|
if (e == nullptr) {
|
||||||
error(us->token, "'using' applied to an unknown entity");
|
error(us->token, "'using' applied to an unknown entity");
|
||||||
return true;
|
return true;
|
||||||
@@ -596,11 +596,11 @@ void add_constant_switch_case(CheckerContext *ctx, Map<TypeAndToken> *seen, Oper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeAndToken tap = {operand.type, ast_node_token(operand.expr)};
|
TypeAndToken tap = {operand.type, ast_token(operand.expr)};
|
||||||
multi_map_insert(seen, key, tap);
|
multi_map_insert(seen, key, tap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_switch_stmt(CheckerContext *ctx, AstNode *node, u32 mod_flags) {
|
void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
|
||||||
ast_node(ss, SwitchStmt, node);
|
ast_node(ss, SwitchStmt, node);
|
||||||
|
|
||||||
Operand x = {};
|
Operand x = {};
|
||||||
@@ -623,21 +623,21 @@ void check_switch_stmt(CheckerContext *ctx, AstNode *node, u32 mod_flags) {
|
|||||||
x.value = exact_value_bool(true);
|
x.value = exact_value_bool(true);
|
||||||
|
|
||||||
Token token = {};
|
Token token = {};
|
||||||
token.pos = ast_node_token(ss->body).pos;
|
token.pos = ast_token(ss->body).pos;
|
||||||
token.string = str_lit("true");
|
token.string = str_lit("true");
|
||||||
|
|
||||||
x.expr = gb_alloc_item(ctx->allocator, AstNode);
|
x.expr = gb_alloc_item(ctx->allocator, Ast);
|
||||||
x.expr->kind = AstNode_Ident;
|
x.expr->kind = Ast_Ident;
|
||||||
x.expr->Ident.token = token;
|
x.expr->Ident.token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(bill): Check for multiple defaults
|
// NOTE(bill): Check for multiple defaults
|
||||||
AstNode *first_default = nullptr;
|
Ast *first_default = nullptr;
|
||||||
ast_node(bs, BlockStmt, ss->body);
|
ast_node(bs, BlockStmt, ss->body);
|
||||||
for_array(i, bs->stmts) {
|
for_array(i, bs->stmts) {
|
||||||
AstNode *stmt = bs->stmts[i];
|
Ast *stmt = bs->stmts[i];
|
||||||
AstNode *default_stmt = nullptr;
|
Ast *default_stmt = nullptr;
|
||||||
if (stmt->kind == AstNode_CaseClause) {
|
if (stmt->kind == Ast_CaseClause) {
|
||||||
ast_node(cc, CaseClause, stmt);
|
ast_node(cc, CaseClause, stmt);
|
||||||
if (cc->list.count == 0) {
|
if (cc->list.count == 0) {
|
||||||
default_stmt = stmt;
|
default_stmt = stmt;
|
||||||
@@ -648,7 +648,7 @@ void check_switch_stmt(CheckerContext *ctx, AstNode *node, u32 mod_flags) {
|
|||||||
|
|
||||||
if (default_stmt != nullptr) {
|
if (default_stmt != nullptr) {
|
||||||
if (first_default != nullptr) {
|
if (first_default != nullptr) {
|
||||||
TokenPos pos = ast_node_token(first_default).pos;
|
TokenPos pos = ast_token(first_default).pos;
|
||||||
error(stmt,
|
error(stmt,
|
||||||
"multiple default clauses\n"
|
"multiple default clauses\n"
|
||||||
"\tfirst at %.*s(%td:%td)",
|
"\tfirst at %.*s(%td:%td)",
|
||||||
@@ -673,17 +673,17 @@ void check_switch_stmt(CheckerContext *ctx, AstNode *node, u32 mod_flags) {
|
|||||||
defer (map_destroy(&seen));
|
defer (map_destroy(&seen));
|
||||||
|
|
||||||
for_array(stmt_index, bs->stmts) {
|
for_array(stmt_index, bs->stmts) {
|
||||||
AstNode *stmt = bs->stmts[stmt_index];
|
Ast *stmt = bs->stmts[stmt_index];
|
||||||
if (stmt->kind != AstNode_CaseClause) {
|
if (stmt->kind != Ast_CaseClause) {
|
||||||
// NOTE(bill): error handled by above multiple default checker
|
// NOTE(bill): error handled by above multiple default checker
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ast_node(cc, CaseClause, stmt);
|
ast_node(cc, CaseClause, stmt);
|
||||||
|
|
||||||
for_array(j, cc->list) {
|
for_array(j, cc->list) {
|
||||||
AstNode *expr = unparen_expr(cc->list[j]);
|
Ast *expr = unparen_expr(cc->list[j]);
|
||||||
|
|
||||||
if (is_ast_node_a_range(expr)) {
|
if (is_ast_range(expr)) {
|
||||||
ast_node(ie, BinaryExpr, expr);
|
ast_node(ie, BinaryExpr, expr);
|
||||||
Operand lhs = {};
|
Operand lhs = {};
|
||||||
Operand rhs = {};
|
Operand rhs = {};
|
||||||
@@ -838,7 +838,7 @@ TypeSwitchKind check_valid_type_switch_type(Type *type) {
|
|||||||
return TypeSwitch_Invalid;
|
return TypeSwitch_Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_type_switch_stmt(CheckerContext *ctx, AstNode *node, u32 mod_flags) {
|
void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
|
||||||
ast_node(ss, TypeSwitchStmt, node);
|
ast_node(ss, TypeSwitchStmt, node);
|
||||||
Operand x = {};
|
Operand x = {};
|
||||||
|
|
||||||
@@ -848,13 +848,13 @@ void check_type_switch_stmt(CheckerContext *ctx, AstNode *node, u32 mod_flags) {
|
|||||||
|
|
||||||
check_label(ctx, ss->label); // TODO(bill): What should the label's "scope" be?
|
check_label(ctx, ss->label); // TODO(bill): What should the label's "scope" be?
|
||||||
|
|
||||||
if (ss->tag->kind != AstNode_AssignStmt) {
|
if (ss->tag->kind != Ast_AssignStmt) {
|
||||||
error(ss->tag, "Expected an 'in' assignment for this type switch statement");
|
error(ss->tag, "Expected an 'in' assignment for this type switch statement");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_node(as, AssignStmt, ss->tag);
|
ast_node(as, AssignStmt, ss->tag);
|
||||||
Token as_token = ast_node_token(ss->tag);
|
Token as_token = ast_token(ss->tag);
|
||||||
if (as->lhs.count != 1) {
|
if (as->lhs.count != 1) {
|
||||||
syntax_error(as_token, "Expected 1 name before 'in'");
|
syntax_error(as_token, "Expected 1 name before 'in'");
|
||||||
return;
|
return;
|
||||||
@@ -863,8 +863,8 @@ void check_type_switch_stmt(CheckerContext *ctx, AstNode *node, u32 mod_flags) {
|
|||||||
syntax_error(as_token, "Expected 1 expression after 'in'");
|
syntax_error(as_token, "Expected 1 expression after 'in'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AstNode *lhs = as->lhs[0];
|
Ast *lhs = as->lhs[0];
|
||||||
AstNode *rhs = as->rhs[0];
|
Ast *rhs = as->rhs[0];
|
||||||
|
|
||||||
check_expr(ctx, &x, rhs);
|
check_expr(ctx, &x, rhs);
|
||||||
check_assignment(ctx, &x, nullptr, str_lit("type switch expression"));
|
check_assignment(ctx, &x, nullptr, str_lit("type switch expression"));
|
||||||
@@ -889,12 +889,12 @@ void check_type_switch_stmt(CheckerContext *ctx, AstNode *node, u32 mod_flags) {
|
|||||||
bool is_ptr = is_type_pointer(x.type);
|
bool is_ptr = is_type_pointer(x.type);
|
||||||
|
|
||||||
// NOTE(bill): Check for multiple defaults
|
// NOTE(bill): Check for multiple defaults
|
||||||
AstNode *first_default = nullptr;
|
Ast *first_default = nullptr;
|
||||||
ast_node(bs, BlockStmt, ss->body);
|
ast_node(bs, BlockStmt, ss->body);
|
||||||
for_array(i, bs->stmts) {
|
for_array(i, bs->stmts) {
|
||||||
AstNode *stmt = bs->stmts[i];
|
Ast *stmt = bs->stmts[i];
|
||||||
AstNode *default_stmt = nullptr;
|
Ast *default_stmt = nullptr;
|
||||||
if (stmt->kind == AstNode_CaseClause) {
|
if (stmt->kind == Ast_CaseClause) {
|
||||||
ast_node(cc, CaseClause, stmt);
|
ast_node(cc, CaseClause, stmt);
|
||||||
if (cc->list.count == 0) {
|
if (cc->list.count == 0) {
|
||||||
default_stmt = stmt;
|
default_stmt = stmt;
|
||||||
@@ -905,7 +905,7 @@ void check_type_switch_stmt(CheckerContext *ctx, AstNode *node, u32 mod_flags) {
|
|||||||
|
|
||||||
if (default_stmt != nullptr) {
|
if (default_stmt != nullptr) {
|
||||||
if (first_default != nullptr) {
|
if (first_default != nullptr) {
|
||||||
TokenPos pos = ast_node_token(first_default).pos;
|
TokenPos pos = ast_token(first_default).pos;
|
||||||
error(stmt,
|
error(stmt,
|
||||||
"Multiple default clauses\n"
|
"Multiple default clauses\n"
|
||||||
"\tfirst at %.*s(%td:%td)",
|
"\tfirst at %.*s(%td:%td)",
|
||||||
@@ -916,8 +916,8 @@ void check_type_switch_stmt(CheckerContext *ctx, AstNode *node, u32 mod_flags) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lhs->kind != AstNode_Ident) {
|
if (lhs->kind != Ast_Ident) {
|
||||||
error(rhs, "Expected an identifier, got '%.*s'", LIT(ast_node_strings[rhs->kind]));
|
error(rhs, "Expected an identifier, got '%.*s'", LIT(ast_strings[rhs->kind]));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -926,8 +926,8 @@ void check_type_switch_stmt(CheckerContext *ctx, AstNode *node, u32 mod_flags) {
|
|||||||
defer (ptr_set_destroy(&seen));
|
defer (ptr_set_destroy(&seen));
|
||||||
|
|
||||||
for_array(i, bs->stmts) {
|
for_array(i, bs->stmts) {
|
||||||
AstNode *stmt = bs->stmts[i];
|
Ast *stmt = bs->stmts[i];
|
||||||
if (stmt->kind != AstNode_CaseClause) {
|
if (stmt->kind != Ast_CaseClause) {
|
||||||
// NOTE(bill): error handled by above multiple default checker
|
// NOTE(bill): error handled by above multiple default checker
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -938,7 +938,7 @@ void check_type_switch_stmt(CheckerContext *ctx, AstNode *node, u32 mod_flags) {
|
|||||||
|
|
||||||
Type *case_type = nullptr;
|
Type *case_type = nullptr;
|
||||||
for_array(type_index, cc->list) {
|
for_array(type_index, cc->list) {
|
||||||
AstNode *type_expr = cc->list[type_index];
|
Ast *type_expr = cc->list[type_index];
|
||||||
if (type_expr != nullptr) { // Otherwise it's a default expression
|
if (type_expr != nullptr) { // Otherwise it's a default expression
|
||||||
Operand y = {};
|
Operand y = {};
|
||||||
check_expr_or_type(ctx, &y, type_expr);
|
check_expr_or_type(ctx, &y, type_expr);
|
||||||
@@ -1046,7 +1046,7 @@ void check_type_switch_stmt(CheckerContext *ctx, AstNode *node, u32 mod_flags) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
|
||||||
u32 mod_flags = flags & (~Stmt_FallthroughAllowed);
|
u32 mod_flags = flags & (~Stmt_FallthroughAllowed);
|
||||||
switch (node->kind) {
|
switch (node->kind) {
|
||||||
case_ast_node(_, EmptyStmt, node); case_end;
|
case_ast_node(_, EmptyStmt, node); case_end;
|
||||||
@@ -1070,8 +1070,8 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
if (kind == Expr_Stmt) {
|
if (kind == Expr_Stmt) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (operand.expr->kind == AstNode_CallExpr) {
|
if (operand.expr->kind == Ast_CallExpr) {
|
||||||
AstNodeCallExpr *ce = &operand.expr->CallExpr;
|
AstCallExpr *ce = &operand.expr->CallExpr;
|
||||||
Type *t = type_of_expr(&ctx->checker->info, ce->proc);
|
Type *t = type_of_expr(&ctx->checker->info, ce->proc);
|
||||||
if (is_type_proc(t)) {
|
if (is_type_proc(t)) {
|
||||||
if (t->Proc.require_results) {
|
if (t->Proc.require_results) {
|
||||||
@@ -1157,7 +1157,7 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
}
|
}
|
||||||
Operand lhs = {Addressing_Invalid};
|
Operand lhs = {Addressing_Invalid};
|
||||||
Operand rhs = {Addressing_Invalid};
|
Operand rhs = {Addressing_Invalid};
|
||||||
AstNode binary_expr = {AstNode_BinaryExpr};
|
Ast binary_expr = {Ast_BinaryExpr};
|
||||||
ast_node(be, BinaryExpr, &binary_expr);
|
ast_node(be, BinaryExpr, &binary_expr);
|
||||||
be->op = op;
|
be->op = op;
|
||||||
be->op.kind = cast(TokenKind)(cast(i32)be->op.kind - (Token_AddEq - Token_Add));
|
be->op.kind = cast(TokenKind)(cast(i32)be->op.kind - (Token_AddEq - Token_Add));
|
||||||
@@ -1201,8 +1201,8 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
|
|
||||||
if (is->else_stmt != nullptr) {
|
if (is->else_stmt != nullptr) {
|
||||||
switch (is->else_stmt->kind) {
|
switch (is->else_stmt->kind) {
|
||||||
case AstNode_IfStmt:
|
case Ast_IfStmt:
|
||||||
case AstNode_BlockStmt:
|
case Ast_BlockStmt:
|
||||||
check_stmt(ctx, is->else_stmt, mod_flags);
|
check_stmt(ctx, is->else_stmt, mod_flags);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1277,8 +1277,8 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
if (fs->post != nullptr) {
|
if (fs->post != nullptr) {
|
||||||
check_stmt(ctx, fs->post, 0);
|
check_stmt(ctx, fs->post, 0);
|
||||||
|
|
||||||
if (fs->post->kind != AstNode_AssignStmt &&
|
if (fs->post->kind != Ast_AssignStmt &&
|
||||||
fs->post->kind != AstNode_IncDecStmt) {
|
fs->post->kind != Ast_IncDecStmt) {
|
||||||
error(fs->post, "'for' statement post statement must be a simple statement");
|
error(fs->post, "'for' statement post statement must be a simple statement");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1299,10 +1299,10 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
isize entity_count = 0;
|
isize entity_count = 0;
|
||||||
bool is_map = false;
|
bool is_map = false;
|
||||||
|
|
||||||
AstNode *expr = unparen_expr(rs->expr);
|
Ast *expr = unparen_expr(rs->expr);
|
||||||
|
|
||||||
|
|
||||||
if (is_ast_node_a_range(expr)) {
|
if (is_ast_range(expr)) {
|
||||||
ast_node(ie, BinaryExpr, expr);
|
ast_node(ie, BinaryExpr, expr);
|
||||||
Operand x = {Addressing_Invalid};
|
Operand x = {Addressing_Invalid};
|
||||||
Operand y = {Addressing_Invalid};
|
Operand y = {Addressing_Invalid};
|
||||||
@@ -1447,18 +1447,18 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
skip_expr:; // NOTE(zhiayang): again, declaring a variable immediately after a label... weird.
|
skip_expr:; // NOTE(zhiayang): again, declaring a variable immediately after a label... weird.
|
||||||
AstNode *lhs[2] = {rs->val0, rs->val1};
|
Ast *lhs[2] = {rs->val0, rs->val1};
|
||||||
Type * rhs[2] = {val0, val1};
|
Type * rhs[2] = {val0, val1};
|
||||||
|
|
||||||
for (isize i = 0; i < 2; i++) {
|
for (isize i = 0; i < 2; i++) {
|
||||||
if (lhs[i] == nullptr) {
|
if (lhs[i] == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
AstNode *name = lhs[i];
|
Ast *name = lhs[i];
|
||||||
Type * type = rhs[i];
|
Type * type = rhs[i];
|
||||||
|
|
||||||
Entity *entity = nullptr;
|
Entity *entity = nullptr;
|
||||||
if (name->kind == AstNode_Ident) {
|
if (name->kind == Ast_Ident) {
|
||||||
Token token = name->Ident.token;
|
Token token = name->Ident.token;
|
||||||
String str = token.string;
|
String str = token.string;
|
||||||
Entity *found = nullptr;
|
Entity *found = nullptr;
|
||||||
@@ -1483,7 +1483,7 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
entity = alloc_entity_dummy_variable(universal_scope, ast_node_token(name));
|
entity = alloc_entity_dummy_variable(universal_scope, ast_token(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
entities[entity_count++] = entity;
|
entities[entity_count++] = entity;
|
||||||
@@ -1513,7 +1513,7 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
|
|
||||||
|
|
||||||
case_ast_node(ds, DeferStmt, node);
|
case_ast_node(ds, DeferStmt, node);
|
||||||
if (is_ast_node_decl(ds->stmt)) {
|
if (is_ast_decl(ds->stmt)) {
|
||||||
error(ds->token, "You cannot defer a declaration");
|
error(ds->token, "You cannot defer a declaration");
|
||||||
} else {
|
} else {
|
||||||
bool out_in_defer = ctx->in_defer;
|
bool out_in_defer = ctx->in_defer;
|
||||||
@@ -1547,11 +1547,11 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bs->label != nullptr) {
|
if (bs->label != nullptr) {
|
||||||
if (bs->label->kind != AstNode_Ident) {
|
if (bs->label->kind != Ast_Ident) {
|
||||||
error(bs->label, "A branch statement's label name must be an identifier");
|
error(bs->label, "A branch statement's label name must be an identifier");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AstNode *ident = bs->label;
|
Ast *ident = bs->label;
|
||||||
String name = ident->Ident.token.string;
|
String name = ident->Ident.token.string;
|
||||||
Operand o = {};
|
Operand o = {};
|
||||||
Entity *e = check_ident(ctx, &o, ident, nullptr, nullptr, false);
|
Entity *e = check_ident(ctx, &o, ident, nullptr, nullptr, false);
|
||||||
@@ -1574,24 +1574,24 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for_array(i, us->list) {
|
for_array(i, us->list) {
|
||||||
AstNode *expr = unparen_expr(us->list[0]);
|
Ast *expr = unparen_expr(us->list[0]);
|
||||||
Entity *e = nullptr;
|
Entity *e = nullptr;
|
||||||
|
|
||||||
bool is_selector = false;
|
bool is_selector = false;
|
||||||
Operand o = {};
|
Operand o = {};
|
||||||
switch (expr->kind) {
|
switch (expr->kind) {
|
||||||
case AstNode_Ident:
|
case Ast_Ident:
|
||||||
e = check_ident(ctx, &o, expr, nullptr, nullptr, true);
|
e = check_ident(ctx, &o, expr, nullptr, nullptr, true);
|
||||||
break;
|
break;
|
||||||
case AstNode_SelectorExpr:
|
case Ast_SelectorExpr:
|
||||||
e = check_selector(ctx, &o, expr, nullptr);
|
e = check_selector(ctx, &o, expr, nullptr);
|
||||||
is_selector = true;
|
is_selector = true;
|
||||||
break;
|
break;
|
||||||
case AstNode_Implicit:
|
case Ast_Implicit:
|
||||||
error(us->token, "'using' applied to an implicit value");
|
error(us->token, "'using' applied to an implicit value");
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
error(us->token, "'using' can only be applied to an entity, got %.*s", LIT(ast_node_strings[expr->kind]));
|
error(us->token, "'using' can only be applied to an entity, got %.*s", LIT(ast_strings[expr->kind]));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1609,9 +1609,9 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(fb, ForeignBlockDecl, node);
|
case_ast_node(fb, ForeignBlockDecl, node);
|
||||||
AstNode *foreign_library = fb->foreign_library;
|
Ast *foreign_library = fb->foreign_library;
|
||||||
CheckerContext c = *ctx;
|
CheckerContext c = *ctx;
|
||||||
if (foreign_library->kind != AstNode_Ident) {
|
if (foreign_library->kind != Ast_Ident) {
|
||||||
error(foreign_library, "foreign library name must be an identifier");
|
error(foreign_library, "foreign library name must be an identifier");
|
||||||
} else {
|
} else {
|
||||||
c.foreign_context.curr_library = foreign_library;
|
c.foreign_context.curr_library = foreign_library;
|
||||||
@@ -1622,8 +1622,8 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
|
|
||||||
ast_node(block, BlockStmt, fb->body);
|
ast_node(block, BlockStmt, fb->body);
|
||||||
for_array(i, block->stmts) {
|
for_array(i, block->stmts) {
|
||||||
AstNode *decl = block->stmts[i];
|
Ast *decl = block->stmts[i];
|
||||||
if (decl->kind == AstNode_ValueDecl && decl->ValueDecl.is_mutable) {
|
if (decl->kind == Ast_ValueDecl && decl->ValueDecl.is_mutable) {
|
||||||
check_stmt(&c, decl, flags);
|
check_stmt(&c, decl, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1636,9 +1636,9 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
|
|
||||||
isize new_name_count = 0;
|
isize new_name_count = 0;
|
||||||
for_array(i, vd->names) {
|
for_array(i, vd->names) {
|
||||||
AstNode *name = vd->names[i];
|
Ast *name = vd->names[i];
|
||||||
Entity *entity = nullptr;
|
Entity *entity = nullptr;
|
||||||
if (name->kind != AstNode_Ident) {
|
if (name->kind != Ast_Ident) {
|
||||||
error(name, "A variable declaration must be an identifier");
|
error(name, "A variable declaration must be an identifier");
|
||||||
} else {
|
} else {
|
||||||
Token token = name->Ident.token;
|
Token token = name->Ident.token;
|
||||||
@@ -1653,9 +1653,9 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
entity = alloc_entity_variable(ctx->scope, token, nullptr, false);
|
entity = alloc_entity_variable(ctx->scope, token, nullptr, false);
|
||||||
entity->identifier = name;
|
entity->identifier = name;
|
||||||
|
|
||||||
AstNode *fl = ctx->foreign_context.curr_library;
|
Ast *fl = ctx->foreign_context.curr_library;
|
||||||
if (fl != nullptr) {
|
if (fl != nullptr) {
|
||||||
GB_ASSERT(fl->kind == AstNode_Ident);
|
GB_ASSERT(fl->kind == Ast_Ident);
|
||||||
entity->Variable.is_foreign = true;
|
entity->Variable.is_foreign = true;
|
||||||
entity->Variable.foreign_library_ident = fl;
|
entity->Variable.foreign_library_ident = fl;
|
||||||
}
|
}
|
||||||
@@ -1669,7 +1669,7 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
entity = alloc_entity_dummy_variable(universal_scope, ast_node_token(name));
|
entity = alloc_entity_dummy_variable(universal_scope, ast_token(name));
|
||||||
}
|
}
|
||||||
entity->parent_proc_decl = ctx->curr_proc_decl;
|
entity->parent_proc_decl = ctx->curr_proc_decl;
|
||||||
entities[entity_count++] = entity;
|
entities[entity_count++] = entity;
|
||||||
@@ -1766,7 +1766,7 @@ void check_stmt_internal(CheckerContext *ctx, AstNode *node, u32 flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (vd->is_using != 0) {
|
if (vd->is_using != 0) {
|
||||||
Token token = ast_node_token(node);
|
Token token = ast_token(node);
|
||||||
if (vd->type != nullptr && entity_count > 1) {
|
if (vd->type != nullptr && entity_count > 1) {
|
||||||
error(token, "'using' can only be applied to one variable of the same type");
|
error(token, "'using' can only be applied to one variable of the same type");
|
||||||
// TODO(bill): Should a 'continue' happen here?
|
// TODO(bill): Should a 'continue' happen here?
|
||||||
|
|||||||
+89
-89
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
void populate_using_entity_scope(CheckerContext *ctx, AstNode *node, Type *t) {
|
void populate_using_entity_scope(CheckerContext *ctx, Ast *node, Type *t) {
|
||||||
t = base_type(type_deref(t));
|
t = base_type(type_deref(t));
|
||||||
gbString str = nullptr;
|
gbString str = nullptr;
|
||||||
defer (gb_string_free(str));
|
defer (gb_string_free(str));
|
||||||
@@ -31,16 +31,16 @@ void populate_using_entity_scope(CheckerContext *ctx, AstNode *node, Type *t) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_struct_fields(CheckerContext *ctx, AstNode *node, Array<Entity *> *fields, Array<AstNode *> const ¶ms,
|
void check_struct_fields(CheckerContext *ctx, Ast *node, Array<Entity *> *fields, Array<Ast *> const ¶ms,
|
||||||
isize init_field_capacity, Type *named_type, String context) {
|
isize init_field_capacity, Type *named_type, String context) {
|
||||||
*fields = array_make<Entity *>(heap_allocator(), 0, init_field_capacity);
|
*fields = array_make<Entity *>(heap_allocator(), 0, init_field_capacity);
|
||||||
|
|
||||||
GB_ASSERT(node->kind == AstNode_StructType);
|
GB_ASSERT(node->kind == Ast_StructType);
|
||||||
|
|
||||||
isize variable_count = 0;
|
isize variable_count = 0;
|
||||||
for_array(i, params) {
|
for_array(i, params) {
|
||||||
AstNode *field = params[i];
|
Ast *field = params[i];
|
||||||
if (ast_node_expect(field, AstNode_Field)) {
|
if (ast_node_expect(field, Ast_Field)) {
|
||||||
ast_node(f, Field, field);
|
ast_node(f, Field, field);
|
||||||
variable_count += gb_max(f->names.count, 1);
|
variable_count += gb_max(f->names.count, 1);
|
||||||
}
|
}
|
||||||
@@ -48,12 +48,12 @@ void check_struct_fields(CheckerContext *ctx, AstNode *node, Array<Entity *> *fi
|
|||||||
|
|
||||||
i32 field_src_index = 0;
|
i32 field_src_index = 0;
|
||||||
for_array(i, params) {
|
for_array(i, params) {
|
||||||
AstNode *param = params[i];
|
Ast *param = params[i];
|
||||||
if (param->kind != AstNode_Field) {
|
if (param->kind != Ast_Field) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ast_node(p, Field, param);
|
ast_node(p, Field, param);
|
||||||
AstNode *type_expr = p->type;
|
Ast *type_expr = p->type;
|
||||||
Type *type = nullptr;
|
Type *type = nullptr;
|
||||||
bool detemine_type_from_operand = false;
|
bool detemine_type_from_operand = false;
|
||||||
|
|
||||||
@@ -80,8 +80,8 @@ void check_struct_fields(CheckerContext *ctx, AstNode *node, Array<Entity *> *fi
|
|||||||
bool is_using = (p->flags&FieldFlag_using) != 0;
|
bool is_using = (p->flags&FieldFlag_using) != 0;
|
||||||
|
|
||||||
for_array(j, p->names) {
|
for_array(j, p->names) {
|
||||||
AstNode *name = p->names[j];
|
Ast *name = p->names[j];
|
||||||
if (!ast_node_expect(name, AstNode_Ident)) {
|
if (!ast_node_expect(name, Ast_Ident)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ void check_struct_fields(CheckerContext *ctx, AstNode *node, Array<Entity *> *fi
|
|||||||
|
|
||||||
if (!is_type_struct(t) && !is_type_raw_union(t) && !is_type_bit_field(t) &&
|
if (!is_type_struct(t) && !is_type_raw_union(t) && !is_type_bit_field(t) &&
|
||||||
p->names.count >= 1 &&
|
p->names.count >= 1 &&
|
||||||
p->names[0]->kind == AstNode_Ident) {
|
p->names[0]->kind == Ast_Ident) {
|
||||||
Token name_token = p->names[0]->Ident.token;
|
Token name_token = p->names[0]->Ident.token;
|
||||||
gbString type_str = type_to_string(first_type);
|
gbString type_str = type_to_string(first_type);
|
||||||
error(name_token, "'using' cannot be applied to the field '%.*s' of type '%s'", LIT(name_token.string), type_str);
|
error(name_token, "'using' cannot be applied to the field '%.*s' of type '%s'", LIT(name_token.string), type_str);
|
||||||
@@ -122,7 +122,7 @@ Entity *make_names_field_for_struct(CheckerContext *ctx, Scope *scope) {
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_custom_align(CheckerContext *ctx, AstNode *node, i64 *align_) {
|
bool check_custom_align(CheckerContext *ctx, Ast *node, i64 *align_) {
|
||||||
GB_ASSERT(align_ != nullptr);
|
GB_ASSERT(align_ != nullptr);
|
||||||
Operand o = {};
|
Operand o = {};
|
||||||
check_expr(ctx, &o, node);
|
check_expr(ctx, &o, node);
|
||||||
@@ -197,18 +197,18 @@ Entity *find_polymorphic_struct_entity(CheckerContext *ctx, Type *original_type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void add_polymorphic_struct_entity(CheckerContext *ctx, AstNode *node, Type *named_type, Type *original_type) {
|
void add_polymorphic_struct_entity(CheckerContext *ctx, Ast *node, Type *named_type, Type *original_type) {
|
||||||
GB_ASSERT(is_type_named(named_type));
|
GB_ASSERT(is_type_named(named_type));
|
||||||
gbAllocator a = heap_allocator();
|
gbAllocator a = heap_allocator();
|
||||||
Scope *s = ctx->scope->parent;
|
Scope *s = ctx->scope->parent;
|
||||||
|
|
||||||
Entity *e = nullptr;
|
Entity *e = nullptr;
|
||||||
{
|
{
|
||||||
Token token = ast_node_token(node);
|
Token token = ast_token(node);
|
||||||
token.kind = Token_String;
|
token.kind = Token_String;
|
||||||
token.string = named_type->Named.name;
|
token.string = named_type->Named.name;
|
||||||
|
|
||||||
AstNode *node = ast_ident(nullptr, token);
|
Ast *node = ast_ident(nullptr, token);
|
||||||
|
|
||||||
e = alloc_entity_type_name(s, token, named_type);
|
e = alloc_entity_type_name(s, token, named_type);
|
||||||
e->state = EntityState_Resolved;
|
e->state = EntityState_Resolved;
|
||||||
@@ -228,7 +228,7 @@ void add_polymorphic_struct_entity(CheckerContext *ctx, AstNode *node, Type *nam
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_struct_type(CheckerContext *ctx, Type *struct_type, AstNode *node, Array<Operand> *poly_operands, Type *named_type, Type *original_type_for_poly) {
|
void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *node, Array<Operand> *poly_operands, Type *named_type, Type *original_type_for_poly) {
|
||||||
GB_ASSERT(is_type_struct(struct_type));
|
GB_ASSERT(is_type_struct(struct_type));
|
||||||
ast_node(st, StructType, node);
|
ast_node(st, StructType, node);
|
||||||
|
|
||||||
@@ -236,7 +236,7 @@ void check_struct_type(CheckerContext *ctx, Type *struct_type, AstNode *node, Ar
|
|||||||
|
|
||||||
isize min_field_count = 0;
|
isize min_field_count = 0;
|
||||||
for_array(field_index, st->fields) {
|
for_array(field_index, st->fields) {
|
||||||
AstNode *field = st->fields[field_index];
|
Ast *field = st->fields[field_index];
|
||||||
switch (field->kind) {
|
switch (field->kind) {
|
||||||
case_ast_node(f, ValueDecl, field);
|
case_ast_node(f, ValueDecl, field);
|
||||||
min_field_count += f->names.count;
|
min_field_count += f->names.count;
|
||||||
@@ -259,12 +259,12 @@ void check_struct_type(CheckerContext *ctx, Type *struct_type, AstNode *node, Ar
|
|||||||
|
|
||||||
if (st->polymorphic_params != nullptr) {
|
if (st->polymorphic_params != nullptr) {
|
||||||
ast_node(field_list, FieldList, st->polymorphic_params);
|
ast_node(field_list, FieldList, st->polymorphic_params);
|
||||||
Array<AstNode *> params = field_list->list;
|
Array<Ast *> params = field_list->list;
|
||||||
if (params.count != 0) {
|
if (params.count != 0) {
|
||||||
isize variable_count = 0;
|
isize variable_count = 0;
|
||||||
for_array(i, params) {
|
for_array(i, params) {
|
||||||
AstNode *field = params[i];
|
Ast *field = params[i];
|
||||||
if (ast_node_expect(field, AstNode_Field)) {
|
if (ast_node_expect(field, Ast_Field)) {
|
||||||
ast_node(f, Field, field);
|
ast_node(f, Field, field);
|
||||||
variable_count += gb_max(f->names.count, 1);
|
variable_count += gb_max(f->names.count, 1);
|
||||||
}
|
}
|
||||||
@@ -273,12 +273,12 @@ void check_struct_type(CheckerContext *ctx, Type *struct_type, AstNode *node, Ar
|
|||||||
auto entities = array_make<Entity *>(ctx->allocator, 0, variable_count);
|
auto entities = array_make<Entity *>(ctx->allocator, 0, variable_count);
|
||||||
|
|
||||||
for_array(i, params) {
|
for_array(i, params) {
|
||||||
AstNode *param = params[i];
|
Ast *param = params[i];
|
||||||
if (param->kind != AstNode_Field) {
|
if (param->kind != Ast_Field) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ast_node(p, Field, param);
|
ast_node(p, Field, param);
|
||||||
AstNode *type_expr = p->type;
|
Ast *type_expr = p->type;
|
||||||
Type *type = nullptr;
|
Type *type = nullptr;
|
||||||
bool is_type_param = false;
|
bool is_type_param = false;
|
||||||
bool is_type_polymorphic_type = false;
|
bool is_type_polymorphic_type = false;
|
||||||
@@ -286,15 +286,15 @@ void check_struct_type(CheckerContext *ctx, Type *struct_type, AstNode *node, Ar
|
|||||||
error(param, "Expected a type for this parameter");
|
error(param, "Expected a type for this parameter");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (type_expr->kind == AstNode_Ellipsis) {
|
if (type_expr->kind == Ast_Ellipsis) {
|
||||||
type_expr = type_expr->Ellipsis.expr;
|
type_expr = type_expr->Ellipsis.expr;
|
||||||
error(param, "A polymorphic parameter cannot be variadic");
|
error(param, "A polymorphic parameter cannot be variadic");
|
||||||
}
|
}
|
||||||
if (type_expr->kind == AstNode_TypeType) {
|
if (type_expr->kind == Ast_TypeType) {
|
||||||
is_type_param = true;
|
is_type_param = true;
|
||||||
Type *specialization = nullptr;
|
Type *specialization = nullptr;
|
||||||
if (type_expr->TypeType.specialization != nullptr) {
|
if (type_expr->TypeType.specialization != nullptr) {
|
||||||
AstNode *s = type_expr->TypeType.specialization;
|
Ast *s = type_expr->TypeType.specialization;
|
||||||
specialization = check_type(ctx, s);
|
specialization = check_type(ctx, s);
|
||||||
// if (!is_type_polymorphic_struct(specialization)) {
|
// if (!is_type_polymorphic_struct(specialization)) {
|
||||||
// gbString str = type_to_string(specialization);
|
// gbString str = type_to_string(specialization);
|
||||||
@@ -339,8 +339,8 @@ void check_struct_type(CheckerContext *ctx, Type *struct_type, AstNode *node, Ar
|
|||||||
|
|
||||||
Scope *scope = ctx->scope;
|
Scope *scope = ctx->scope;
|
||||||
for_array(j, p->names) {
|
for_array(j, p->names) {
|
||||||
AstNode *name = p->names[j];
|
Ast *name = p->names[j];
|
||||||
if (!ast_node_expect(name, AstNode_Ident)) {
|
if (!ast_node_expect(name, Ast_Ident)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Entity *e = nullptr;
|
Entity *e = nullptr;
|
||||||
@@ -431,7 +431,7 @@ void check_struct_type(CheckerContext *ctx, Type *struct_type, AstNode *node, Ar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void check_union_type(CheckerContext *ctx, Type *union_type, AstNode *node) {
|
void check_union_type(CheckerContext *ctx, Type *union_type, Ast *node) {
|
||||||
GB_ASSERT(is_type_union(union_type));
|
GB_ASSERT(is_type_union(union_type));
|
||||||
ast_node(ut, UnionType, node);
|
ast_node(ut, UnionType, node);
|
||||||
|
|
||||||
@@ -444,7 +444,7 @@ void check_union_type(CheckerContext *ctx, Type *union_type, AstNode *node) {
|
|||||||
union_type->Union.scope = ctx->scope;
|
union_type->Union.scope = ctx->scope;
|
||||||
|
|
||||||
for_array(i, ut->variants) {
|
for_array(i, ut->variants) {
|
||||||
AstNode *node = ut->variants[i];
|
Ast *node = ut->variants[i];
|
||||||
Type *t = check_type_expr(ctx, node, nullptr);
|
Type *t = check_type_expr(ctx, node, nullptr);
|
||||||
if (t != nullptr && t != t_invalid) {
|
if (t != nullptr && t != t_invalid) {
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
@@ -485,7 +485,7 @@ void check_union_type(CheckerContext *ctx, Type *union_type, AstNode *node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, AstNode *node) {
|
void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast *node) {
|
||||||
ast_node(et, EnumType, node);
|
ast_node(et, EnumType, node);
|
||||||
GB_ASSERT(is_type_enum(enum_type));
|
GB_ASSERT(is_type_enum(enum_type));
|
||||||
|
|
||||||
@@ -521,18 +521,18 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast
|
|||||||
scope_reserve(ctx->scope, et->fields.count);
|
scope_reserve(ctx->scope, et->fields.count);
|
||||||
|
|
||||||
for_array(i, et->fields) {
|
for_array(i, et->fields) {
|
||||||
AstNode *field = et->fields[i];
|
Ast *field = et->fields[i];
|
||||||
AstNode *ident = nullptr;
|
Ast *ident = nullptr;
|
||||||
AstNode *init = nullptr;
|
Ast *init = nullptr;
|
||||||
if (field->kind == AstNode_FieldValue) {
|
if (field->kind == Ast_FieldValue) {
|
||||||
ast_node(fv, FieldValue, field);
|
ast_node(fv, FieldValue, field);
|
||||||
if (fv->field == nullptr || fv->field->kind != AstNode_Ident) {
|
if (fv->field == nullptr || fv->field->kind != Ast_Ident) {
|
||||||
error(field, "An enum field's name must be an identifier");
|
error(field, "An enum field's name must be an identifier");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ident = fv->field;
|
ident = fv->field;
|
||||||
init = fv->value;
|
init = fv->value;
|
||||||
} else if (field->kind == AstNode_Ident) {
|
} else if (field->kind == Ast_Ident) {
|
||||||
ident = field;
|
ident = field;
|
||||||
} else {
|
} else {
|
||||||
error(field, "An enum field's name must be an identifier");
|
error(field, "An enum field's name must be an identifier");
|
||||||
@@ -634,7 +634,7 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, AstNode *node) {
|
void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, Ast *node) {
|
||||||
ast_node(bft, BitFieldType, node);
|
ast_node(bft, BitFieldType, node);
|
||||||
GB_ASSERT(is_type_bit_field(bit_field_type));
|
GB_ASSERT(is_type_bit_field(bit_field_type));
|
||||||
|
|
||||||
@@ -646,12 +646,12 @@ void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, AstNode *no
|
|||||||
|
|
||||||
u32 curr_offset = 0;
|
u32 curr_offset = 0;
|
||||||
for_array(i, bft->fields) {
|
for_array(i, bft->fields) {
|
||||||
AstNode *field = bft->fields[i];
|
Ast *field = bft->fields[i];
|
||||||
GB_ASSERT(field->kind == AstNode_FieldValue);
|
GB_ASSERT(field->kind == Ast_FieldValue);
|
||||||
AstNode *ident = field->FieldValue.field;
|
Ast *ident = field->FieldValue.field;
|
||||||
AstNode *value = field->FieldValue.value;
|
Ast *value = field->FieldValue.value;
|
||||||
|
|
||||||
if (ident->kind != AstNode_Ident) {
|
if (ident->kind != Ast_Ident) {
|
||||||
error(field, "A bit field value's name must be an identifier");
|
error(field, "A bit field value's name must be an identifier");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -786,7 +786,7 @@ Type *determine_type_from_polymorphic(CheckerContext *ctx, Type *poly_type, Oper
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Type *check_get_params(CheckerContext *ctx, Scope *scope, AstNode *_params, bool *is_variadic_, isize *variadic_index_, bool *success_, isize *specialization_count_, Array<Operand> *operands) {
|
Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is_variadic_, isize *variadic_index_, bool *success_, isize *specialization_count_, Array<Operand> *operands) {
|
||||||
if (_params == nullptr) {
|
if (_params == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -795,7 +795,7 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, AstNode *_params, bool
|
|||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
ast_node(field_list, FieldList, _params);
|
ast_node(field_list, FieldList, _params);
|
||||||
Array<AstNode *> params = field_list->list;
|
Array<Ast *> params = field_list->list;
|
||||||
|
|
||||||
if (params.count == 0) {
|
if (params.count == 0) {
|
||||||
if (success_) *success_ = success;
|
if (success_) *success_ = success;
|
||||||
@@ -806,16 +806,16 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, AstNode *_params, bool
|
|||||||
|
|
||||||
isize variable_count = 0;
|
isize variable_count = 0;
|
||||||
for_array(i, params) {
|
for_array(i, params) {
|
||||||
AstNode *field = params[i];
|
Ast *field = params[i];
|
||||||
if (ast_node_expect(field, AstNode_Field)) {
|
if (ast_node_expect(field, Ast_Field)) {
|
||||||
ast_node(f, Field, field);
|
ast_node(f, Field, field);
|
||||||
variable_count += gb_max(f->names.count, 1);
|
variable_count += gb_max(f->names.count, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isize min_variable_count = variable_count;
|
isize min_variable_count = variable_count;
|
||||||
for (isize i = params.count-1; i >= 0; i--) {
|
for (isize i = params.count-1; i >= 0; i--) {
|
||||||
AstNode *field = params[i];
|
Ast *field = params[i];
|
||||||
if (field->kind == AstNode_Field) {
|
if (field->kind == Ast_Field) {
|
||||||
ast_node(f, Field, field);
|
ast_node(f, Field, field);
|
||||||
if (f->default_value == nullptr) {
|
if (f->default_value == nullptr) {
|
||||||
break;
|
break;
|
||||||
@@ -830,14 +830,14 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, AstNode *_params, bool
|
|||||||
bool is_c_vararg = false;
|
bool is_c_vararg = false;
|
||||||
auto variables = array_make<Entity *>(ctx->allocator, 0, variable_count);
|
auto variables = array_make<Entity *>(ctx->allocator, 0, variable_count);
|
||||||
for_array(i, params) {
|
for_array(i, params) {
|
||||||
AstNode *param = params[i];
|
Ast *param = params[i];
|
||||||
if (param->kind != AstNode_Field) {
|
if (param->kind != Ast_Field) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ast_node(p, Field, param);
|
ast_node(p, Field, param);
|
||||||
AstNode *type_expr = p->type;
|
Ast *type_expr = p->type;
|
||||||
Type *type = nullptr;
|
Type *type = nullptr;
|
||||||
AstNode *default_value = unparen_expr(p->default_value);
|
Ast *default_value = unparen_expr(p->default_value);
|
||||||
ExactValue value = {};
|
ExactValue value = {};
|
||||||
bool default_is_nil = false;
|
bool default_is_nil = false;
|
||||||
bool default_is_location = false;
|
bool default_is_location = false;
|
||||||
@@ -849,7 +849,7 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, AstNode *_params, bool
|
|||||||
bool is_using = (p->flags&FieldFlag_using) != 0;
|
bool is_using = (p->flags&FieldFlag_using) != 0;
|
||||||
|
|
||||||
if (type_expr == nullptr) {
|
if (type_expr == nullptr) {
|
||||||
if (default_value->kind == AstNode_BasicDirective &&
|
if (default_value->kind == Ast_BasicDirective &&
|
||||||
default_value->BasicDirective.name == "caller_location") {
|
default_value->BasicDirective.name == "caller_location") {
|
||||||
init_core_source_code_location(ctx->checker);
|
init_core_source_code_location(ctx->checker);
|
||||||
default_is_location = true;
|
default_is_location = true;
|
||||||
@@ -860,15 +860,15 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, AstNode *_params, bool
|
|||||||
if (is_operand_nil(o)) {
|
if (is_operand_nil(o)) {
|
||||||
default_is_nil = true;
|
default_is_nil = true;
|
||||||
} else if (o.mode != Addressing_Constant) {
|
} else if (o.mode != Addressing_Constant) {
|
||||||
if (default_value->kind == AstNode_ProcLit) {
|
if (default_value->kind == Ast_ProcLit) {
|
||||||
value = exact_value_procedure(default_value);
|
value = exact_value_procedure(default_value);
|
||||||
} else {
|
} else {
|
||||||
Entity *e = nullptr;
|
Entity *e = nullptr;
|
||||||
if (o.mode == Addressing_Value && is_type_proc(o.type)) {
|
if (o.mode == Addressing_Value && is_type_proc(o.type)) {
|
||||||
Operand x = {};
|
Operand x = {};
|
||||||
if (default_value->kind == AstNode_Ident) {
|
if (default_value->kind == Ast_Ident) {
|
||||||
e = check_ident(ctx, &x, default_value, nullptr, nullptr, false);
|
e = check_ident(ctx, &x, default_value, nullptr, nullptr, false);
|
||||||
} else if (default_value->kind == AstNode_SelectorExpr) {
|
} else if (default_value->kind == Ast_SelectorExpr) {
|
||||||
e = check_selector(ctx, &x, default_value, nullptr);
|
e = check_selector(ctx, &x, default_value, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -888,7 +888,7 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, AstNode *_params, bool
|
|||||||
type = default_type(o.type);
|
type = default_type(o.type);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (type_expr->kind == AstNode_Ellipsis) {
|
if (type_expr->kind == Ast_Ellipsis) {
|
||||||
type_expr = type_expr->Ellipsis.expr;
|
type_expr = type_expr->Ellipsis.expr;
|
||||||
#if 1
|
#if 1
|
||||||
is_variadic = true;
|
is_variadic = true;
|
||||||
@@ -906,7 +906,7 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, AstNode *_params, bool
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (type_expr->kind == AstNode_TypeType) {
|
if (type_expr->kind == Ast_TypeType) {
|
||||||
ast_node(tt, TypeType, type_expr);
|
ast_node(tt, TypeType, type_expr);
|
||||||
is_type_param = true;
|
is_type_param = true;
|
||||||
specialization = check_type(ctx, tt->specialization);
|
specialization = check_type(ctx, tt->specialization);
|
||||||
@@ -942,12 +942,12 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, AstNode *_params, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (default_value != nullptr) {
|
if (default_value != nullptr) {
|
||||||
if (type_expr->kind == AstNode_TypeType) {
|
if (type_expr->kind == Ast_TypeType) {
|
||||||
error(default_value, "A type parameter may not have a default value");
|
error(default_value, "A type parameter may not have a default value");
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
Operand o = {};
|
Operand o = {};
|
||||||
if (default_value->kind == AstNode_BasicDirective &&
|
if (default_value->kind == Ast_BasicDirective &&
|
||||||
default_value->BasicDirective.name == "caller_location") {
|
default_value->BasicDirective.name == "caller_location") {
|
||||||
init_core_source_code_location(ctx->checker);
|
init_core_source_code_location(ctx->checker);
|
||||||
default_is_location = true;
|
default_is_location = true;
|
||||||
@@ -959,15 +959,15 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, AstNode *_params, bool
|
|||||||
if (is_operand_nil(o)) {
|
if (is_operand_nil(o)) {
|
||||||
default_is_nil = true;
|
default_is_nil = true;
|
||||||
} else if (o.mode != Addressing_Constant) {
|
} else if (o.mode != Addressing_Constant) {
|
||||||
if (default_value->kind == AstNode_ProcLit) {
|
if (default_value->kind == Ast_ProcLit) {
|
||||||
value = exact_value_procedure(default_value);
|
value = exact_value_procedure(default_value);
|
||||||
} else {
|
} else {
|
||||||
Entity *e = nullptr;
|
Entity *e = nullptr;
|
||||||
if (o.mode == Addressing_Value && is_type_proc(o.type)) {
|
if (o.mode == Addressing_Value && is_type_proc(o.type)) {
|
||||||
Operand x = {};
|
Operand x = {};
|
||||||
if (default_value->kind == AstNode_Ident) {
|
if (default_value->kind == Ast_Ident) {
|
||||||
e = check_ident(ctx, &x, default_value, nullptr, nullptr, false);
|
e = check_ident(ctx, &x, default_value, nullptr, nullptr, false);
|
||||||
} else if (default_value->kind == AstNode_SelectorExpr) {
|
} else if (default_value->kind == Ast_SelectorExpr) {
|
||||||
e = check_selector(ctx, &x, default_value, nullptr);
|
e = check_selector(ctx, &x, default_value, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1010,7 +1010,7 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, AstNode *_params, bool
|
|||||||
|
|
||||||
if (p->flags&FieldFlag_c_vararg) {
|
if (p->flags&FieldFlag_c_vararg) {
|
||||||
if (p->type == nullptr ||
|
if (p->type == nullptr ||
|
||||||
p->type->kind != AstNode_Ellipsis) {
|
p->type->kind != Ast_Ellipsis) {
|
||||||
error(param, "'#c_vararg' can only be applied to variadic type fields");
|
error(param, "'#c_vararg' can only be applied to variadic type fields");
|
||||||
p->flags &= ~FieldFlag_c_vararg; // Remove the flag
|
p->flags &= ~FieldFlag_c_vararg; // Remove the flag
|
||||||
} else {
|
} else {
|
||||||
@@ -1031,8 +1031,8 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, AstNode *_params, bool
|
|||||||
bool is_in = (p->flags&FieldFlag_in) != 0;
|
bool is_in = (p->flags&FieldFlag_in) != 0;
|
||||||
|
|
||||||
for_array(j, p->names) {
|
for_array(j, p->names) {
|
||||||
AstNode *name = p->names[j];
|
Ast *name = p->names[j];
|
||||||
if (!ast_node_expect(name, AstNode_Ident)) {
|
if (!ast_node_expect(name, Ast_Ident)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1150,12 +1150,12 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, AstNode *_params, bool
|
|||||||
return tuple;
|
return tuple;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *check_get_results(CheckerContext *ctx, Scope *scope, AstNode *_results) {
|
Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) {
|
||||||
if (_results == nullptr) {
|
if (_results == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
ast_node(field_list, FieldList, _results);
|
ast_node(field_list, FieldList, _results);
|
||||||
Array<AstNode *> results = field_list->list;
|
Array<Ast *> results = field_list->list;
|
||||||
|
|
||||||
if (results.count == 0) {
|
if (results.count == 0) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -1164,8 +1164,8 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, AstNode *_results) {
|
|||||||
|
|
||||||
isize variable_count = 0;
|
isize variable_count = 0;
|
||||||
for_array(i, results) {
|
for_array(i, results) {
|
||||||
AstNode *field = results[i];
|
Ast *field = results[i];
|
||||||
if (ast_node_expect(field, AstNode_Field)) {
|
if (ast_node_expect(field, Ast_Field)) {
|
||||||
ast_node(f, Field, field);
|
ast_node(f, Field, field);
|
||||||
variable_count += gb_max(f->names.count, 1);
|
variable_count += gb_max(f->names.count, 1);
|
||||||
}
|
}
|
||||||
@@ -1174,7 +1174,7 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, AstNode *_results) {
|
|||||||
auto variables = array_make<Entity *>(ctx->allocator, 0, variable_count);
|
auto variables = array_make<Entity *>(ctx->allocator, 0, variable_count);
|
||||||
for_array(i, results) {
|
for_array(i, results) {
|
||||||
ast_node(field, Field, results[i]);
|
ast_node(field, Field, results[i]);
|
||||||
AstNode *default_value = unparen_expr(field->default_value);
|
Ast *default_value = unparen_expr(field->default_value);
|
||||||
ExactValue value = {};
|
ExactValue value = {};
|
||||||
bool default_is_nil = false;
|
bool default_is_nil = false;
|
||||||
|
|
||||||
@@ -1220,7 +1220,7 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, AstNode *_results) {
|
|||||||
|
|
||||||
|
|
||||||
if (field->names.count == 0) {
|
if (field->names.count == 0) {
|
||||||
Token token = ast_node_token(field->type);
|
Token token = ast_token(field->type);
|
||||||
token.string = str_lit("");
|
token.string = str_lit("");
|
||||||
Entity *param = alloc_entity_param(scope, token, type, false, false);
|
Entity *param = alloc_entity_param(scope, token, type, false, false);
|
||||||
param->Variable.default_value = value;
|
param->Variable.default_value = value;
|
||||||
@@ -1228,14 +1228,14 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, AstNode *_results) {
|
|||||||
array_add(&variables, param);
|
array_add(&variables, param);
|
||||||
} else {
|
} else {
|
||||||
for_array(j, field->names) {
|
for_array(j, field->names) {
|
||||||
Token token = ast_node_token(results[i]);
|
Token token = ast_token(results[i]);
|
||||||
if (field->type != nullptr) {
|
if (field->type != nullptr) {
|
||||||
token = ast_node_token(field->type);
|
token = ast_token(field->type);
|
||||||
}
|
}
|
||||||
token.string = str_lit("");
|
token.string = str_lit("");
|
||||||
|
|
||||||
AstNode *name = field->names[j];
|
Ast *name = field->names[j];
|
||||||
if (name->kind != AstNode_Ident) {
|
if (name->kind != Ast_Ident) {
|
||||||
error(name, "Expected an identifer for as the field name");
|
error(name, "Expected an identifer for as the field name");
|
||||||
} else {
|
} else {
|
||||||
token = name->Ident.token;
|
token = name->Ident.token;
|
||||||
@@ -1466,7 +1466,7 @@ bool abi_compat_return_by_value(gbAllocator a, ProcCallingConvention cc, Type *a
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(bill): 'operands' is for generating non generic procedure type
|
// NOTE(bill): 'operands' is for generating non generic procedure type
|
||||||
bool check_procedure_type(CheckerContext *ctx, Type *type, AstNode *proc_type_node, Array<Operand> *operands) {
|
bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, Array<Operand> *operands) {
|
||||||
ast_node(pt, ProcType, proc_type_node);
|
ast_node(pt, ProcType, proc_type_node);
|
||||||
|
|
||||||
if (ctx->polymorphic_scope == nullptr && ctx->allow_polymorphic_types) {
|
if (ctx->polymorphic_scope == nullptr && ctx->allow_polymorphic_types) {
|
||||||
@@ -1572,11 +1572,11 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, AstNode *proc_type_no
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
i64 check_array_count(CheckerContext *ctx, Operand *o, AstNode *e) {
|
i64 check_array_count(CheckerContext *ctx, Operand *o, Ast *e) {
|
||||||
if (e == nullptr) {
|
if (e == nullptr) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (e->kind == AstNode_UnaryExpr &&
|
if (e->kind == Ast_UnaryExpr &&
|
||||||
e->UnaryExpr.op.kind == Token_Ellipsis) {
|
e->UnaryExpr.op.kind == Token_Ellipsis) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1641,7 +1641,7 @@ void init_map_entry_type(Type *type) {
|
|||||||
value: Value;
|
value: Value;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
AstNode *dummy_node = alloc_ast_node(nullptr, AstNode_Invalid);
|
Ast *dummy_node = alloc_ast_node(nullptr, Ast_Invalid);
|
||||||
Scope *s = create_scope(universal_scope, a);
|
Scope *s = create_scope(universal_scope, a);
|
||||||
|
|
||||||
auto fields = array_make<Entity *>(a, 0, 3);
|
auto fields = array_make<Entity *>(a, 0, 3);
|
||||||
@@ -1676,7 +1676,7 @@ void init_map_internal_types(Type *type) {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
gbAllocator a = heap_allocator();
|
gbAllocator a = heap_allocator();
|
||||||
AstNode *dummy_node = alloc_ast_node(nullptr, AstNode_Invalid);
|
Ast *dummy_node = alloc_ast_node(nullptr, Ast_Invalid);
|
||||||
Scope *s = create_scope(universal_scope, a);
|
Scope *s = create_scope(universal_scope, a);
|
||||||
|
|
||||||
Type *hashes_type = alloc_type_dynamic_array(t_int);
|
Type *hashes_type = alloc_type_dynamic_array(t_int);
|
||||||
@@ -1695,7 +1695,7 @@ void init_map_internal_types(Type *type) {
|
|||||||
type->Map.lookup_result_type = make_optional_ok_type(value);
|
type->Map.lookup_result_type = make_optional_ok_type(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_map_type(CheckerContext *ctx, Type *type, AstNode *node) {
|
void check_map_type(CheckerContext *ctx, Type *type, Ast *node) {
|
||||||
GB_ASSERT(type->kind == Type_Map);
|
GB_ASSERT(type->kind == Type_Map);
|
||||||
ast_node(mt, MapType, node);
|
ast_node(mt, MapType, node);
|
||||||
|
|
||||||
@@ -1728,7 +1728,7 @@ void check_map_type(CheckerContext *ctx, Type *type, AstNode *node) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool check_type_internal(CheckerContext *ctx, AstNode *e, Type **type, Type *named_type) {
|
bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_type) {
|
||||||
GB_ASSERT_NOT_NULL(type);
|
GB_ASSERT_NOT_NULL(type);
|
||||||
if (e == nullptr) {
|
if (e == nullptr) {
|
||||||
*type = t_invalid;
|
*type = t_invalid;
|
||||||
@@ -1792,8 +1792,8 @@ bool check_type_internal(CheckerContext *ctx, AstNode *e, Type **type, Type *nam
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(pt, PolyType, e);
|
case_ast_node(pt, PolyType, e);
|
||||||
AstNode *ident = pt->type;
|
Ast *ident = pt->type;
|
||||||
if (ident->kind != AstNode_Ident) {
|
if (ident->kind != Ast_Ident) {
|
||||||
error(ident, "Expected an identifier after the $");
|
error(ident, "Expected an identifier after the $");
|
||||||
*type = t_invalid;
|
*type = t_invalid;
|
||||||
return false;
|
return false;
|
||||||
@@ -1805,7 +1805,7 @@ bool check_type_internal(CheckerContext *ctx, AstNode *e, Type **type, Type *nam
|
|||||||
CheckerContext c = *ctx;
|
CheckerContext c = *ctx;
|
||||||
c.in_polymorphic_specialization = true;
|
c.in_polymorphic_specialization = true;
|
||||||
|
|
||||||
AstNode *s = pt->specialization;
|
Ast *s = pt->specialization;
|
||||||
specific = check_type(&c, s);
|
specific = check_type(&c, s);
|
||||||
}
|
}
|
||||||
Type *t = alloc_type_generic(ctx->scope, 0, token.string, specific);
|
Type *t = alloc_type_generic(ctx->scope, 0, token.string, specific);
|
||||||
@@ -2009,7 +2009,7 @@ bool check_type_internal(CheckerContext *ctx, AstNode *e, Type **type, Type *nam
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *check_type(CheckerContext *ctx, AstNode *e) {
|
Type *check_type(CheckerContext *ctx, Ast *e) {
|
||||||
CheckerContext c = *ctx;
|
CheckerContext c = *ctx;
|
||||||
c.type_path = new_checker_type_path();
|
c.type_path = new_checker_type_path();
|
||||||
defer (destroy_checker_type_path(c.type_path));
|
defer (destroy_checker_type_path(c.type_path));
|
||||||
@@ -2017,7 +2017,7 @@ Type *check_type(CheckerContext *ctx, AstNode *e) {
|
|||||||
return check_type_expr(&c, e, nullptr);
|
return check_type_expr(&c, e, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *check_type_expr(CheckerContext *ctx, AstNode *e, Type *named_type) {
|
Type *check_type_expr(CheckerContext *ctx, Ast *e, Type *named_type) {
|
||||||
Type *type = nullptr;
|
Type *type = nullptr;
|
||||||
bool ok = check_type_internal(ctx, e, &type, named_type);
|
bool ok = check_type_internal(ctx, e, &type, named_type);
|
||||||
|
|
||||||
|
|||||||
+125
-125
@@ -1,7 +1,7 @@
|
|||||||
#include "entity.cpp"
|
#include "entity.cpp"
|
||||||
#include "types.cpp"
|
#include "types.cpp"
|
||||||
|
|
||||||
void check_expr(CheckerContext *c, Operand *operand, AstNode *expression);
|
void check_expr(CheckerContext *c, Operand *operand, Ast *expression);
|
||||||
|
|
||||||
|
|
||||||
bool is_operand_value(Operand o) {
|
bool is_operand_value(Operand o) {
|
||||||
@@ -165,10 +165,10 @@ void import_graph_node_swap(ImportGraphNode **data, isize i, isize j) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GB_COMPARE_PROC(ast_node_cmp) {
|
GB_COMPARE_PROC(ast_node_cmp) {
|
||||||
AstNode *x = *cast(AstNode **)a;
|
Ast *x = *cast(Ast **)a;
|
||||||
AstNode *y = *cast(AstNode **)b;
|
Ast *y = *cast(Ast **)b;
|
||||||
Token i = ast_node_token(x);
|
Token i = ast_token(x);
|
||||||
Token j = ast_node_token(y);
|
Token j = ast_token(y);
|
||||||
return token_pos_cmp(i.pos, j.pos);
|
return token_pos_cmp(i.pos, j.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,7 +307,7 @@ void destroy_scope(Scope *scope) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void add_scope(CheckerContext *c, AstNode *node, Scope *scope) {
|
void add_scope(CheckerContext *c, Ast *node, Scope *scope) {
|
||||||
GB_ASSERT(node != nullptr);
|
GB_ASSERT(node != nullptr);
|
||||||
GB_ASSERT(scope != nullptr);
|
GB_ASSERT(scope != nullptr);
|
||||||
scope->node = node;
|
scope->node = node;
|
||||||
@@ -315,20 +315,20 @@ void add_scope(CheckerContext *c, AstNode *node, Scope *scope) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_open_scope(CheckerContext *c, AstNode *node) {
|
void check_open_scope(CheckerContext *c, Ast *node) {
|
||||||
node = unparen_expr(node);
|
node = unparen_expr(node);
|
||||||
GB_ASSERT(node->kind == AstNode_Invalid ||
|
GB_ASSERT(node->kind == Ast_Invalid ||
|
||||||
is_ast_node_stmt(node) ||
|
is_ast_stmt(node) ||
|
||||||
is_ast_node_type(node));
|
is_ast_type(node));
|
||||||
Scope *scope = create_scope(c->scope, c->allocator);
|
Scope *scope = create_scope(c->scope, c->allocator);
|
||||||
add_scope(c, node, scope);
|
add_scope(c, node, scope);
|
||||||
switch (node->kind) {
|
switch (node->kind) {
|
||||||
case AstNode_ProcType:
|
case Ast_ProcType:
|
||||||
scope->is_proc = true;
|
scope->is_proc = true;
|
||||||
break;
|
break;
|
||||||
case AstNode_StructType:
|
case Ast_StructType:
|
||||||
case AstNode_EnumType:
|
case Ast_EnumType:
|
||||||
case AstNode_UnionType:
|
case Ast_UnionType:
|
||||||
scope->is_struct = true;
|
scope->is_struct = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -662,26 +662,26 @@ void destroy_checker(Checker *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Entity *entity_of_ident(AstNode *identifier) {
|
Entity *entity_of_ident(Ast *identifier) {
|
||||||
if (identifier->kind == AstNode_Ident) {
|
if (identifier->kind == Ast_Ident) {
|
||||||
return identifier->Ident.entity;
|
return identifier->Ident.entity;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeAndValue type_and_value_of_expr(CheckerInfo *i, AstNode *expr) {
|
TypeAndValue type_and_value_of_expr(CheckerInfo *i, Ast *expr) {
|
||||||
TypeAndValue result = {};
|
TypeAndValue result = {};
|
||||||
TypeAndValue *found = map_get(&i->types, hash_node(expr));
|
TypeAndValue *found = map_get(&i->types, hash_node(expr));
|
||||||
if (found) result = *found;
|
if (found) result = *found;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *type_of_expr(CheckerInfo *i, AstNode *expr) {
|
Type *type_of_expr(CheckerInfo *i, Ast *expr) {
|
||||||
TypeAndValue tav = type_and_value_of_expr(i, expr);
|
TypeAndValue tav = type_and_value_of_expr(i, expr);
|
||||||
if (tav.mode != Addressing_Invalid) {
|
if (tav.mode != Addressing_Invalid) {
|
||||||
return tav.type;
|
return tav.type;
|
||||||
}
|
}
|
||||||
if (expr->kind == AstNode_Ident) {
|
if (expr->kind == Ast_Ident) {
|
||||||
Entity *entity = entity_of_ident(expr);
|
Entity *entity = entity_of_ident(expr);
|
||||||
if (entity) {
|
if (entity) {
|
||||||
return entity->type;
|
return entity->type;
|
||||||
@@ -691,12 +691,12 @@ Type *type_of_expr(CheckerInfo *i, AstNode *expr) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity *implicit_entity_of_node(CheckerInfo *i, AstNode *clause) {
|
Entity *implicit_entity_of_node(CheckerInfo *i, Ast *clause) {
|
||||||
// Entity **found = map_get(&i->implicits, hash_node(clause));
|
// Entity **found = map_get(&i->implicits, hash_node(clause));
|
||||||
// if (found != nullptr) {
|
// if (found != nullptr) {
|
||||||
// return *found;
|
// return *found;
|
||||||
// }
|
// }
|
||||||
if (clause->kind == AstNode_CaseClause) {
|
if (clause->kind == Ast_CaseClause) {
|
||||||
return clause->CaseClause.implicit_entity;
|
return clause->CaseClause.implicit_entity;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -707,15 +707,15 @@ bool is_entity_implicitly_imported(Entity *import_name, Entity *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Will return nullptr if not found
|
// Will return nullptr if not found
|
||||||
Entity *entity_of_node(CheckerInfo *i, AstNode *expr) {
|
Entity *entity_of_node(CheckerInfo *i, Ast *expr) {
|
||||||
expr = unparen_expr(expr);
|
expr = unparen_expr(expr);
|
||||||
switch (expr->kind) {
|
switch (expr->kind) {
|
||||||
case_ast_node(ident, Ident, expr);
|
case_ast_node(ident, Ident, expr);
|
||||||
return entity_of_ident(expr);
|
return entity_of_ident(expr);
|
||||||
case_end;
|
case_end;
|
||||||
case_ast_node(se, SelectorExpr, expr);
|
case_ast_node(se, SelectorExpr, expr);
|
||||||
AstNode *s = unselector_expr(se->selector);
|
Ast *s = unselector_expr(se->selector);
|
||||||
if (s->kind == AstNode_Ident) {
|
if (s->kind == Ast_Ident) {
|
||||||
return entity_of_ident(s);
|
return entity_of_ident(s);
|
||||||
}
|
}
|
||||||
case_end;
|
case_end;
|
||||||
@@ -734,7 +734,7 @@ DeclInfo *decl_info_of_entity(Entity *e) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclInfo *decl_info_of_ident(AstNode *ident) {
|
DeclInfo *decl_info_of_ident(Ast *ident) {
|
||||||
return decl_info_of_entity(entity_of_ident(ident));
|
return decl_info_of_entity(entity_of_ident(ident));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -745,16 +745,16 @@ AstFile *ast_file_of_filename(CheckerInfo *i, String filename) {
|
|||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
Scope *scope_of_node(AstNode *node) {
|
Scope *scope_of_node(Ast *node) {
|
||||||
return node->scope;
|
return node->scope;
|
||||||
}
|
}
|
||||||
ExprInfo *check_get_expr_info(CheckerInfo *i, AstNode *expr) {
|
ExprInfo *check_get_expr_info(CheckerInfo *i, Ast *expr) {
|
||||||
return map_get(&i->untyped, hash_node(expr));
|
return map_get(&i->untyped, hash_node(expr));
|
||||||
}
|
}
|
||||||
void check_set_expr_info(CheckerInfo *i, AstNode *expr, ExprInfo info) {
|
void check_set_expr_info(CheckerInfo *i, Ast *expr, ExprInfo info) {
|
||||||
map_set(&i->untyped, hash_node(expr), info);
|
map_set(&i->untyped, hash_node(expr), info);
|
||||||
}
|
}
|
||||||
void check_remove_expr_info(CheckerInfo *i, AstNode *expr) {
|
void check_remove_expr_info(CheckerInfo *i, Ast *expr) {
|
||||||
map_remove(&i->untyped, hash_node(expr));
|
map_remove(&i->untyped, hash_node(expr));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -794,7 +794,7 @@ isize type_info_index(CheckerInfo *info, Type *type, bool error_on_failure) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void add_untyped(CheckerInfo *i, AstNode *expression, bool lhs, AddressingMode mode, Type *type, ExactValue value) {
|
void add_untyped(CheckerInfo *i, Ast *expression, bool lhs, AddressingMode mode, Type *type, ExactValue value) {
|
||||||
if (expression == nullptr) {
|
if (expression == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -807,7 +807,7 @@ void add_untyped(CheckerInfo *i, AstNode *expression, bool lhs, AddressingMode m
|
|||||||
map_set(&i->untyped, hash_node(expression), make_expr_info(mode, type, value, lhs));
|
map_set(&i->untyped, hash_node(expression), make_expr_info(mode, type, value, lhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode, Type *type, ExactValue value) {
|
void add_type_and_value(CheckerInfo *i, Ast *expression, AddressingMode mode, Type *type, ExactValue value) {
|
||||||
if (expression == nullptr) {
|
if (expression == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -825,9 +825,9 @@ void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode
|
|||||||
map_set(&i->types, hash_node(expression), tv);
|
map_set(&i->types, hash_node(expression), tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity) {
|
void add_entity_definition(CheckerInfo *i, Ast *identifier, Entity *entity) {
|
||||||
GB_ASSERT(identifier != nullptr);
|
GB_ASSERT(identifier != nullptr);
|
||||||
GB_ASSERT(identifier->kind == AstNode_Ident);
|
GB_ASSERT(identifier->kind == Ast_Ident);
|
||||||
if (is_blank_ident(identifier)) {
|
if (is_blank_ident(identifier)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -842,7 +842,7 @@ void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity)
|
|||||||
array_add(&i->definitions, entity);
|
array_add(&i->definitions, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) {
|
bool add_entity(Checker *c, Scope *scope, Ast *identifier, Entity *entity) {
|
||||||
if (scope == nullptr) {
|
if (scope == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -883,12 +883,12 @@ bool add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_entity_use(CheckerContext *c, AstNode *identifier, Entity *entity) {
|
void add_entity_use(CheckerContext *c, Ast *identifier, Entity *entity) {
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (identifier != nullptr) {
|
if (identifier != nullptr) {
|
||||||
if (identifier->kind != AstNode_Ident) {
|
if (identifier->kind != Ast_Ident) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (entity->identifier == nullptr) {
|
if (entity->identifier == nullptr) {
|
||||||
@@ -906,8 +906,8 @@ void add_entity_use(CheckerContext *c, AstNode *identifier, Entity *entity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void add_entity_and_decl_info(CheckerContext *c, AstNode *identifier, Entity *e, DeclInfo *d) {
|
void add_entity_and_decl_info(CheckerContext *c, Ast *identifier, Entity *e, DeclInfo *d) {
|
||||||
GB_ASSERT(identifier->kind == AstNode_Ident);
|
GB_ASSERT(identifier->kind == Ast_Ident);
|
||||||
GB_ASSERT(e != nullptr && d != nullptr);
|
GB_ASSERT(e != nullptr && d != nullptr);
|
||||||
GB_ASSERT(identifier->Ident.token.string == e->token.string);
|
GB_ASSERT(identifier->Ident.token.string == e->token.string);
|
||||||
|
|
||||||
@@ -931,10 +931,10 @@ void add_entity_and_decl_info(CheckerContext *c, AstNode *identifier, Entity *e,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void add_implicit_entity(CheckerContext *c, AstNode *clause, Entity *e) {
|
void add_implicit_entity(CheckerContext *c, Ast *clause, Entity *e) {
|
||||||
GB_ASSERT(clause != nullptr);
|
GB_ASSERT(clause != nullptr);
|
||||||
GB_ASSERT(e != nullptr);
|
GB_ASSERT(e != nullptr);
|
||||||
GB_ASSERT(clause->kind == AstNode_CaseClause);
|
GB_ASSERT(clause->kind == Ast_CaseClause);
|
||||||
clause->CaseClause.implicit_entity = e;
|
clause->CaseClause.implicit_entity = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1098,7 +1098,7 @@ void check_procedure_later(Checker *c, ProcInfo info) {
|
|||||||
array_add(&c->procs_to_check, info);
|
array_add(&c->procs_to_check, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *decl, Type *type, AstNode *body, u64 tags) {
|
void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *decl, Type *type, Ast *body, u64 tags) {
|
||||||
ProcInfo info = {};
|
ProcInfo info = {};
|
||||||
info.file = file;
|
info.file = file;
|
||||||
info.token = token;
|
info.token = token;
|
||||||
@@ -1798,7 +1798,7 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void check_decl_attributes(CheckerContext *c, Array<AstNode *> const &attributes, DeclAttributeProc *proc, AttributeContext *ac) {
|
void check_decl_attributes(CheckerContext *c, Array<Ast *> const &attributes, DeclAttributeProc *proc, AttributeContext *ac) {
|
||||||
if (attributes.count == 0) return;
|
if (attributes.count == 0) return;
|
||||||
|
|
||||||
String original_link_prefix = {};
|
String original_link_prefix = {};
|
||||||
@@ -1811,19 +1811,19 @@ void check_decl_attributes(CheckerContext *c, Array<AstNode *> const &attributes
|
|||||||
defer (string_set_destroy(&set));
|
defer (string_set_destroy(&set));
|
||||||
|
|
||||||
for_array(i, attributes) {
|
for_array(i, attributes) {
|
||||||
AstNode *attr = attributes[i];
|
Ast *attr = attributes[i];
|
||||||
if (attr->kind != AstNode_Attribute) continue;
|
if (attr->kind != Ast_Attribute) continue;
|
||||||
for_array(j, attr->Attribute.elems) {
|
for_array(j, attr->Attribute.elems) {
|
||||||
AstNode *elem = attr->Attribute.elems[j];
|
Ast *elem = attr->Attribute.elems[j];
|
||||||
String name = {};
|
String name = {};
|
||||||
AstNode *value = nullptr;
|
Ast *value = nullptr;
|
||||||
|
|
||||||
switch (elem->kind) {
|
switch (elem->kind) {
|
||||||
case_ast_node(i, Ident, elem);
|
case_ast_node(i, Ident, elem);
|
||||||
name = i->token.string;
|
name = i->token.string;
|
||||||
case_end;
|
case_end;
|
||||||
case_ast_node(fv, FieldValue, elem);
|
case_ast_node(fv, FieldValue, elem);
|
||||||
GB_ASSERT(fv->field->kind == AstNode_Ident);
|
GB_ASSERT(fv->field->kind == Ast_Ident);
|
||||||
name = fv->field->Ident.token.string;
|
name = fv->field->Ident.token.string;
|
||||||
value = fv->value;
|
value = fv->value;
|
||||||
case_end;
|
case_end;
|
||||||
@@ -1869,7 +1869,7 @@ void check_decl_attributes(CheckerContext *c, Array<AstNode *> const &attributes
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool check_arity_match(CheckerContext *c, AstNodeValueDecl *vd, bool is_global) {
|
bool check_arity_match(CheckerContext *c, AstValueDecl *vd, bool is_global) {
|
||||||
isize lhs = vd->names.count;
|
isize lhs = vd->names.count;
|
||||||
isize rhs = vd->values.count;
|
isize rhs = vd->values.count;
|
||||||
|
|
||||||
@@ -1880,7 +1880,7 @@ bool check_arity_match(CheckerContext *c, AstNodeValueDecl *vd, bool is_global)
|
|||||||
}
|
}
|
||||||
} else if (lhs < rhs) {
|
} else if (lhs < rhs) {
|
||||||
if (lhs < vd->values.count) {
|
if (lhs < vd->values.count) {
|
||||||
AstNode *n = vd->values[lhs];
|
Ast *n = vd->values[lhs];
|
||||||
gbString str = expr_to_string(n);
|
gbString str = expr_to_string(n);
|
||||||
error(n, "Extra initial expression '%s'", str);
|
error(n, "Extra initial expression '%s'", str);
|
||||||
gb_string_free(str);
|
gb_string_free(str);
|
||||||
@@ -1890,13 +1890,13 @@ bool check_arity_match(CheckerContext *c, AstNodeValueDecl *vd, bool is_global)
|
|||||||
return false;
|
return false;
|
||||||
} else if (lhs > rhs) {
|
} else if (lhs > rhs) {
|
||||||
if (!is_global && rhs != 1) {
|
if (!is_global && rhs != 1) {
|
||||||
AstNode *n = vd->names[rhs];
|
Ast *n = vd->names[rhs];
|
||||||
gbString str = expr_to_string(n);
|
gbString str = expr_to_string(n);
|
||||||
error(n, "Missing expression for '%s'", str);
|
error(n, "Missing expression for '%s'", str);
|
||||||
gb_string_free(str);
|
gb_string_free(str);
|
||||||
return false;
|
return false;
|
||||||
} else if (is_global) {
|
} else if (is_global) {
|
||||||
AstNode *n = vd->values[rhs-1];
|
Ast *n = vd->values[rhs-1];
|
||||||
error(n, "Expected %td expressions on the right hand side, got %td", lhs, rhs);
|
error(n, "Expected %td expressions on the right hand side, got %td", lhs, rhs);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1905,7 +1905,7 @@ bool check_arity_match(CheckerContext *c, AstNodeValueDecl *vd, bool is_global)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_collect_entities_from_when_stmt(CheckerContext *c, AstNodeWhenStmt *ws) {
|
void check_collect_entities_from_when_stmt(CheckerContext *c, AstWhenStmt *ws) {
|
||||||
Operand operand = {Addressing_Invalid};
|
Operand operand = {Addressing_Invalid};
|
||||||
if (!ws->is_cond_determined) {
|
if (!ws->is_cond_determined) {
|
||||||
check_expr(c, &operand, ws->cond);
|
check_expr(c, &operand, ws->cond);
|
||||||
@@ -1920,17 +1920,17 @@ void check_collect_entities_from_when_stmt(CheckerContext *c, AstNodeWhenStmt *w
|
|||||||
ws->determined_cond = operand.value.kind == ExactValue_Bool && operand.value.value_bool;
|
ws->determined_cond = operand.value.kind == ExactValue_Bool && operand.value.value_bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ws->body == nullptr || ws->body->kind != AstNode_BlockStmt) {
|
if (ws->body == nullptr || ws->body->kind != Ast_BlockStmt) {
|
||||||
error(ws->cond, "Invalid body for 'when' statement");
|
error(ws->cond, "Invalid body for 'when' statement");
|
||||||
} else {
|
} else {
|
||||||
if (ws->determined_cond) {
|
if (ws->determined_cond) {
|
||||||
check_collect_entities(c, ws->body->BlockStmt.stmts);
|
check_collect_entities(c, ws->body->BlockStmt.stmts);
|
||||||
} else if (ws->else_stmt) {
|
} else if (ws->else_stmt) {
|
||||||
switch (ws->else_stmt->kind) {
|
switch (ws->else_stmt->kind) {
|
||||||
case AstNode_BlockStmt:
|
case Ast_BlockStmt:
|
||||||
check_collect_entities(c, ws->else_stmt->BlockStmt.stmts);
|
check_collect_entities(c, ws->else_stmt->BlockStmt.stmts);
|
||||||
break;
|
break;
|
||||||
case AstNode_WhenStmt:
|
case Ast_WhenStmt:
|
||||||
check_collect_entities_from_when_stmt(c, &ws->else_stmt->WhenStmt);
|
check_collect_entities_from_when_stmt(c, &ws->else_stmt->WhenStmt);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1941,7 +1941,7 @@ void check_collect_entities_from_when_stmt(CheckerContext *c, AstNodeWhenStmt *w
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_builtin_attributes(CheckerContext *ctx, Entity *e, Array<AstNode *> *attributes) {
|
void check_builtin_attributes(CheckerContext *ctx, Entity *e, Array<Ast *> *attributes) {
|
||||||
switch (e->kind) {
|
switch (e->kind) {
|
||||||
case Entity_ProcGroup:
|
case Entity_ProcGroup:
|
||||||
case Entity_Procedure:
|
case Entity_Procedure:
|
||||||
@@ -1956,19 +1956,19 @@ void check_builtin_attributes(CheckerContext *ctx, Entity *e, Array<AstNode *> *
|
|||||||
}
|
}
|
||||||
|
|
||||||
for_array(j, *attributes) {
|
for_array(j, *attributes) {
|
||||||
AstNode *attr = (*attributes)[j];
|
Ast *attr = (*attributes)[j];
|
||||||
if (attr->kind != AstNode_Attribute) continue;
|
if (attr->kind != Ast_Attribute) continue;
|
||||||
for (isize k = 0; k < attr->Attribute.elems.count; k++) {
|
for (isize k = 0; k < attr->Attribute.elems.count; k++) {
|
||||||
AstNode *elem = attr->Attribute.elems[k];
|
Ast *elem = attr->Attribute.elems[k];
|
||||||
String name = {};
|
String name = {};
|
||||||
AstNode *value = nullptr;
|
Ast *value = nullptr;
|
||||||
|
|
||||||
switch (elem->kind) {
|
switch (elem->kind) {
|
||||||
case_ast_node(i, Ident, elem);
|
case_ast_node(i, Ident, elem);
|
||||||
name = i->token.string;
|
name = i->token.string;
|
||||||
case_end;
|
case_end;
|
||||||
case_ast_node(fv, FieldValue, elem);
|
case_ast_node(fv, FieldValue, elem);
|
||||||
GB_ASSERT(fv->field->kind == AstNode_Ident);
|
GB_ASSERT(fv->field->kind == Ast_Ident);
|
||||||
name = fv->field->Ident.token.string;
|
name = fv->field->Ident.token.string;
|
||||||
value = fv->value;
|
value = fv->value;
|
||||||
case_end;
|
case_end;
|
||||||
@@ -1991,8 +1991,8 @@ void check_builtin_attributes(CheckerContext *ctx, Entity *e, Array<AstNode *> *
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (isize i = 0; i < attributes->count; i++) {
|
for (isize i = 0; i < attributes->count; i++) {
|
||||||
AstNode *attr = (*attributes)[i];
|
Ast *attr = (*attributes)[i];
|
||||||
if (attr->kind != AstNode_Attribute) continue;
|
if (attr->kind != Ast_Attribute) continue;
|
||||||
if (attr->Attribute.elems.count == 0) {
|
if (attr->Attribute.elems.count == 0) {
|
||||||
(*attributes)[i] = (*attributes)[attributes->count-1];
|
(*attributes)[i] = (*attributes)[attributes->count-1];
|
||||||
attributes->count--;
|
attributes->count--;
|
||||||
@@ -2001,7 +2001,7 @@ void check_builtin_attributes(CheckerContext *ctx, Entity *e, Array<AstNode *> *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_collect_value_decl(CheckerContext *c, AstNode *decl) {
|
void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
||||||
if (decl->been_handled) return;
|
if (decl->been_handled) return;
|
||||||
decl->been_handled = true;
|
decl->been_handled = true;
|
||||||
|
|
||||||
@@ -2027,13 +2027,13 @@ void check_collect_value_decl(CheckerContext *c, AstNode *decl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for_array(i, vd->names) {
|
for_array(i, vd->names) {
|
||||||
AstNode *name = vd->names[i];
|
Ast *name = vd->names[i];
|
||||||
AstNode *value = nullptr;
|
Ast *value = nullptr;
|
||||||
if (i < vd->values.count) {
|
if (i < vd->values.count) {
|
||||||
value = vd->values[i];
|
value = vd->values[i];
|
||||||
}
|
}
|
||||||
if (name->kind != AstNode_Ident) {
|
if (name->kind != Ast_Ident) {
|
||||||
error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
|
error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_strings[name->kind]));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Entity *e = alloc_entity_variable(c->scope, name->Ident.token, nullptr, false);
|
Entity *e = alloc_entity_variable(c->scope, name->Ident.token, nullptr, false);
|
||||||
@@ -2044,9 +2044,9 @@ void check_collect_value_decl(CheckerContext *c, AstNode *decl) {
|
|||||||
error(name, "'using' is not allowed at the file scope");
|
error(name, "'using' is not allowed at the file scope");
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *fl = c->foreign_context.curr_library;
|
Ast *fl = c->foreign_context.curr_library;
|
||||||
if (fl != nullptr) {
|
if (fl != nullptr) {
|
||||||
GB_ASSERT(fl->kind == AstNode_Ident);
|
GB_ASSERT(fl->kind == Ast_Ident);
|
||||||
e->Variable.is_foreign = true;
|
e->Variable.is_foreign = true;
|
||||||
e->Variable.foreign_library_ident = fl;
|
e->Variable.foreign_library_ident = fl;
|
||||||
|
|
||||||
@@ -2060,7 +2060,7 @@ void check_collect_value_decl(CheckerContext *c, AstNode *decl) {
|
|||||||
|
|
||||||
DeclInfo *d = di;
|
DeclInfo *d = di;
|
||||||
if (d == nullptr || i > 0) {
|
if (d == nullptr || i > 0) {
|
||||||
AstNode *init_expr = value;
|
Ast *init_expr = value;
|
||||||
d = make_decl_info(heap_allocator(), e->scope, c->decl);
|
d = make_decl_info(heap_allocator(), e->scope, c->decl);
|
||||||
d->type_expr = vd->type;
|
d->type_expr = vd->type;
|
||||||
d->init_expr = init_expr;
|
d->init_expr = init_expr;
|
||||||
@@ -2077,13 +2077,13 @@ void check_collect_value_decl(CheckerContext *c, AstNode *decl) {
|
|||||||
check_arity_match(c, vd, true);
|
check_arity_match(c, vd, true);
|
||||||
} else {
|
} else {
|
||||||
for_array(i, vd->names) {
|
for_array(i, vd->names) {
|
||||||
AstNode *name = vd->names[i];
|
Ast *name = vd->names[i];
|
||||||
if (name->kind != AstNode_Ident) {
|
if (name->kind != Ast_Ident) {
|
||||||
error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
|
error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_strings[name->kind]));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *init = unparen_expr(vd->values[i]);
|
Ast *init = unparen_expr(vd->values[i]);
|
||||||
if (init == nullptr) {
|
if (init == nullptr) {
|
||||||
error(name, "Expected a value for this constant value declaration");
|
error(name, "Expected a value for this constant value declaration");
|
||||||
continue;
|
continue;
|
||||||
@@ -2091,21 +2091,21 @@ void check_collect_value_decl(CheckerContext *c, AstNode *decl) {
|
|||||||
|
|
||||||
Token token = name->Ident.token;
|
Token token = name->Ident.token;
|
||||||
|
|
||||||
AstNode *fl = c->foreign_context.curr_library;
|
Ast *fl = c->foreign_context.curr_library;
|
||||||
DeclInfo *d = make_decl_info(c->allocator, c->scope, c->decl);
|
DeclInfo *d = make_decl_info(c->allocator, c->scope, c->decl);
|
||||||
Entity *e = nullptr;
|
Entity *e = nullptr;
|
||||||
|
|
||||||
d->attributes = vd->attributes;
|
d->attributes = vd->attributes;
|
||||||
|
|
||||||
if (is_ast_node_type(init) ||
|
if (is_ast_type(init) ||
|
||||||
(vd->type != nullptr && vd->type->kind == AstNode_TypeType)) {
|
(vd->type != nullptr && vd->type->kind == Ast_TypeType)) {
|
||||||
e = alloc_entity_type_name(d->scope, token, nullptr);
|
e = alloc_entity_type_name(d->scope, token, nullptr);
|
||||||
if (vd->type != nullptr) {
|
if (vd->type != nullptr) {
|
||||||
error(name, "A type declaration cannot have an type parameter");
|
error(name, "A type declaration cannot have an type parameter");
|
||||||
}
|
}
|
||||||
d->type_expr = init;
|
d->type_expr = init;
|
||||||
d->init_expr = init;
|
d->init_expr = init;
|
||||||
} else if (init->kind == AstNode_ProcLit) {
|
} else if (init->kind == Ast_ProcLit) {
|
||||||
if (c->scope->is_struct) {
|
if (c->scope->is_struct) {
|
||||||
error(name, "Procedure declarations are not allowed within a struct");
|
error(name, "Procedure declarations are not allowed within a struct");
|
||||||
continue;
|
continue;
|
||||||
@@ -2113,11 +2113,11 @@ void check_collect_value_decl(CheckerContext *c, AstNode *decl) {
|
|||||||
ast_node(pl, ProcLit, init);
|
ast_node(pl, ProcLit, init);
|
||||||
e = alloc_entity_procedure(d->scope, token, nullptr, pl->tags);
|
e = alloc_entity_procedure(d->scope, token, nullptr, pl->tags);
|
||||||
if (fl != nullptr) {
|
if (fl != nullptr) {
|
||||||
GB_ASSERT(fl->kind == AstNode_Ident);
|
GB_ASSERT(fl->kind == Ast_Ident);
|
||||||
e->Procedure.foreign_library_ident = fl;
|
e->Procedure.foreign_library_ident = fl;
|
||||||
e->Procedure.is_foreign = true;
|
e->Procedure.is_foreign = true;
|
||||||
|
|
||||||
GB_ASSERT(pl->type->kind == AstNode_ProcType);
|
GB_ASSERT(pl->type->kind == Ast_ProcType);
|
||||||
auto cc = pl->type->ProcType.calling_convention;
|
auto cc = pl->type->ProcType.calling_convention;
|
||||||
if (cc == ProcCC_ForeignBlockDefault) {
|
if (cc == ProcCC_ForeignBlockDefault) {
|
||||||
cc = ProcCC_CDecl;
|
cc = ProcCC_CDecl;
|
||||||
@@ -2135,7 +2135,7 @@ void check_collect_value_decl(CheckerContext *c, AstNode *decl) {
|
|||||||
}
|
}
|
||||||
d->proc_lit = init;
|
d->proc_lit = init;
|
||||||
d->type_expr = pl->type;
|
d->type_expr = pl->type;
|
||||||
} else if (init->kind == AstNode_ProcGroup) {
|
} else if (init->kind == Ast_ProcGroup) {
|
||||||
ast_node(pg, ProcGroup, init);
|
ast_node(pg, ProcGroup, init);
|
||||||
e = alloc_entity_proc_group(d->scope, token, nullptr);
|
e = alloc_entity_proc_group(d->scope, token, nullptr);
|
||||||
if (fl != nullptr) {
|
if (fl != nullptr) {
|
||||||
@@ -2151,9 +2151,9 @@ void check_collect_value_decl(CheckerContext *c, AstNode *decl) {
|
|||||||
|
|
||||||
if (e->kind != Entity_Procedure) {
|
if (e->kind != Entity_Procedure) {
|
||||||
if (fl != nullptr || c->foreign_context.in_export) {
|
if (fl != nullptr || c->foreign_context.in_export) {
|
||||||
AstNodeKind kind = init->kind;
|
AstKind kind = init->kind;
|
||||||
error(name, "Only procedures and variables are allowed to be in a foreign block, got %.*s", LIT(ast_node_strings[kind]));
|
error(name, "Only procedures and variables are allowed to be in a foreign block, got %.*s", LIT(ast_strings[kind]));
|
||||||
if (kind == AstNode_ProcType) {
|
if (kind == Ast_ProcType) {
|
||||||
gb_printf_err("\tDid you forget to append '---' to the procedure?\n");
|
gb_printf_err("\tDid you forget to append '---' to the procedure?\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2168,17 +2168,17 @@ void check_collect_value_decl(CheckerContext *c, AstNode *decl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_add_foreign_block_decl(CheckerContext *ctx, AstNode *decl) {
|
void check_add_foreign_block_decl(CheckerContext *ctx, Ast *decl) {
|
||||||
if (decl->been_handled) return;
|
if (decl->been_handled) return;
|
||||||
decl->been_handled = true;
|
decl->been_handled = true;
|
||||||
|
|
||||||
ast_node(fb, ForeignBlockDecl, decl);
|
ast_node(fb, ForeignBlockDecl, decl);
|
||||||
AstNode *foreign_library = fb->foreign_library;
|
Ast *foreign_library = fb->foreign_library;
|
||||||
|
|
||||||
CheckerContext c = *ctx;
|
CheckerContext c = *ctx;
|
||||||
if (foreign_library->kind == AstNode_Ident) {
|
if (foreign_library->kind == Ast_Ident) {
|
||||||
c.foreign_context.curr_library = foreign_library;
|
c.foreign_context.curr_library = foreign_library;
|
||||||
} else if (foreign_library->kind == AstNode_Implicit && foreign_library->Implicit.kind == Token_export) {
|
} else if (foreign_library->kind == Ast_Implicit && foreign_library->Implicit.kind == Token_export) {
|
||||||
c.foreign_context.in_export = true;
|
c.foreign_context.in_export = true;
|
||||||
} else {
|
} else {
|
||||||
error(foreign_library, "Foreign block name must be an identifier or 'export'");
|
error(foreign_library, "Foreign block name must be an identifier or 'export'");
|
||||||
@@ -2193,13 +2193,13 @@ void check_add_foreign_block_decl(CheckerContext *ctx, AstNode *decl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(bill): If file_scopes == nullptr, this will act like a local scope
|
// NOTE(bill): If file_scopes == nullptr, this will act like a local scope
|
||||||
void check_collect_entities(CheckerContext *c, Array<AstNode *> const &nodes) {
|
void check_collect_entities(CheckerContext *c, Array<Ast *> const &nodes) {
|
||||||
for_array(decl_index, nodes) {
|
for_array(decl_index, nodes) {
|
||||||
AstNode *decl = nodes[decl_index];
|
Ast *decl = nodes[decl_index];
|
||||||
if (!is_ast_node_decl(decl) && !is_ast_node_when_stmt(decl)) {
|
if (!is_ast_decl(decl) && !is_ast_when_stmt(decl)) {
|
||||||
if (c->scope->is_file && decl->kind == AstNode_ExprStmt) {
|
if (c->scope->is_file && decl->kind == Ast_ExprStmt) {
|
||||||
AstNode *expr = decl->ExprStmt.expr;
|
Ast *expr = decl->ExprStmt.expr;
|
||||||
if (expr->kind == AstNode_CallExpr && expr->CallExpr.proc->kind == AstNode_BasicDirective) {
|
if (expr->kind == Ast_CallExpr && expr->CallExpr.proc->kind == Ast_BasicDirective) {
|
||||||
if (c->collect_delayed_decls) {
|
if (c->collect_delayed_decls) {
|
||||||
array_add(&c->scope->delayed_directives, expr);
|
array_add(&c->scope->delayed_directives, expr);
|
||||||
}
|
}
|
||||||
@@ -2259,7 +2259,7 @@ void check_collect_entities(CheckerContext *c, Array<AstNode *> const &nodes) {
|
|||||||
// declared after this stmt in source
|
// declared after this stmt in source
|
||||||
if (!c->scope->is_file || c->collect_delayed_decls) {
|
if (!c->scope->is_file || c->collect_delayed_decls) {
|
||||||
for_array(i, nodes) {
|
for_array(i, nodes) {
|
||||||
AstNode *node = nodes[i];
|
Ast *node = nodes[i];
|
||||||
switch (node->kind) {
|
switch (node->kind) {
|
||||||
case_ast_node(ws, WhenStmt, node);
|
case_ast_node(ws, WhenStmt, node);
|
||||||
check_collect_entities_from_when_stmt(c, ws);
|
check_collect_entities_from_when_stmt(c, ws);
|
||||||
@@ -2378,7 +2378,7 @@ String path_to_entity_name(String name, String fullpath) {
|
|||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
|
||||||
void add_import_dependency_node(Checker *c, AstNode *decl, Map<ImportGraphNode *> *M) {
|
void add_import_dependency_node(Checker *c, Ast *decl, Map<ImportGraphNode *> *M) {
|
||||||
AstPackage *parent_pkg = decl->file->pkg;
|
AstPackage *parent_pkg = decl->file->pkg;
|
||||||
|
|
||||||
switch (decl->kind) {
|
switch (decl->kind) {
|
||||||
@@ -2391,7 +2391,7 @@ void add_import_dependency_node(Checker *c, AstNode *decl, Map<ImportGraphNode *
|
|||||||
AstPackage *pkg = c->info.packages.entries[pkg_index].value;
|
AstPackage *pkg = c->info.packages.entries[pkg_index].value;
|
||||||
gb_printf_err("%.*s\n", LIT(pkg->fullpath));
|
gb_printf_err("%.*s\n", LIT(pkg->fullpath));
|
||||||
}
|
}
|
||||||
Token token = ast_node_token(decl);
|
Token token = ast_token(decl);
|
||||||
gb_printf_err("%.*s(%td:%td)\n", LIT(token.pos.file), token.pos.line, token.pos.column);
|
gb_printf_err("%.*s(%td:%td)\n", LIT(token.pos.file), token.pos.line, token.pos.column);
|
||||||
GB_PANIC("Unable to find package: %.*s", LIT(path));
|
GB_PANIC("Unable to find package: %.*s", LIT(path));
|
||||||
}
|
}
|
||||||
@@ -2428,7 +2428,7 @@ void add_import_dependency_node(Checker *c, AstNode *decl, Map<ImportGraphNode *
|
|||||||
|
|
||||||
if (ws->else_stmt != nullptr) {
|
if (ws->else_stmt != nullptr) {
|
||||||
switch (ws->else_stmt->kind) {
|
switch (ws->else_stmt->kind) {
|
||||||
case AstNode_BlockStmt: {
|
case Ast_BlockStmt: {
|
||||||
auto stmts = ws->else_stmt->BlockStmt.stmts;
|
auto stmts = ws->else_stmt->BlockStmt.stmts;
|
||||||
for_array(i, stmts) {
|
for_array(i, stmts) {
|
||||||
add_import_dependency_node(c, stmts[i], M);
|
add_import_dependency_node(c, stmts[i], M);
|
||||||
@@ -2436,7 +2436,7 @@ void add_import_dependency_node(Checker *c, AstNode *decl, Map<ImportGraphNode *
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AstNode_WhenStmt:
|
case Ast_WhenStmt:
|
||||||
add_import_dependency_node(c, ws->else_stmt, M);
|
add_import_dependency_node(c, ws->else_stmt, M);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2462,7 +2462,7 @@ Array<ImportGraphNode *> generate_import_dependency_graph(Checker *c) {
|
|||||||
for_array(j, p->files) {
|
for_array(j, p->files) {
|
||||||
AstFile *f = p->files[j];
|
AstFile *f = p->files[j];
|
||||||
for_array(k, f->decls) {
|
for_array(k, f->decls) {
|
||||||
AstNode *decl = f->decls[k];
|
Ast *decl = f->decls[k];
|
||||||
add_import_dependency_node(c, decl, &M);
|
add_import_dependency_node(c, decl, &M);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2484,7 +2484,7 @@ Array<ImportGraphNode *> generate_import_dependency_graph(Checker *c) {
|
|||||||
|
|
||||||
struct ImportPathItem {
|
struct ImportPathItem {
|
||||||
AstPackage *pkg;
|
AstPackage *pkg;
|
||||||
AstNode * decl;
|
Ast * decl;
|
||||||
};
|
};
|
||||||
|
|
||||||
Array<ImportPathItem> find_import_path(Checker *c, AstPackage *start, AstPackage *end, PtrSet<AstPackage *> *visited) {
|
Array<ImportPathItem> find_import_path(Checker *c, AstPackage *start, AstPackage *end, PtrSet<AstPackage *> *visited) {
|
||||||
@@ -2507,8 +2507,8 @@ Array<ImportPathItem> find_import_path(Checker *c, AstPackage *start, AstPackage
|
|||||||
AstFile *f = pkg->files[i];
|
AstFile *f = pkg->files[i];
|
||||||
for_array(j, f->imports) {
|
for_array(j, f->imports) {
|
||||||
AstPackage *pkg = nullptr;
|
AstPackage *pkg = nullptr;
|
||||||
AstNode *decl = f->imports[j];
|
Ast *decl = f->imports[j];
|
||||||
if (decl->kind == AstNode_ImportDecl) {
|
if (decl->kind == Ast_ImportDecl) {
|
||||||
pkg = decl->ImportDecl.package;
|
pkg = decl->ImportDecl.package;
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
@@ -2537,7 +2537,7 @@ Array<ImportPathItem> find_import_path(Checker *c, AstPackage *start, AstPackage
|
|||||||
return empty_path;
|
return empty_path;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void check_add_import_decl(CheckerContext *ctx, AstNode *decl) {
|
void check_add_import_decl(CheckerContext *ctx, Ast *decl) {
|
||||||
if (decl->been_handled) return;
|
if (decl->been_handled) return;
|
||||||
decl->been_handled = true;
|
decl->been_handled = true;
|
||||||
|
|
||||||
@@ -2624,7 +2624,7 @@ void check_add_import_decl(CheckerContext *ctx, AstNode *decl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_add_foreign_import_decl(CheckerContext *ctx, AstNode *decl) {
|
void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) {
|
||||||
if (decl->been_handled) return;
|
if (decl->been_handled) return;
|
||||||
decl->been_handled = true;
|
decl->been_handled = true;
|
||||||
|
|
||||||
@@ -2667,10 +2667,10 @@ void check_add_foreign_import_decl(CheckerContext *ctx, AstNode *decl) {
|
|||||||
add_entity(ctx->checker, parent_scope, nullptr, e);
|
add_entity(ctx->checker, parent_scope, nullptr, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool collect_checked_packages_from_decl_list(Checker *c, Array<AstNode *> const &decls) {
|
bool collect_checked_packages_from_decl_list(Checker *c, Array<Ast *> const &decls) {
|
||||||
bool new_files = false;
|
bool new_files = false;
|
||||||
for_array(i, decls) {
|
for_array(i, decls) {
|
||||||
AstNode *decl = decls[i];
|
Ast *decl = decls[i];
|
||||||
switch (decl->kind) {
|
switch (decl->kind) {
|
||||||
case_ast_node(id, ImportDecl, decl);
|
case_ast_node(id, ImportDecl, decl);
|
||||||
HashKey key = hash_string(id->fullpath);
|
HashKey key = hash_string(id->fullpath);
|
||||||
@@ -2690,10 +2690,10 @@ bool collect_checked_packages_from_decl_list(Checker *c, Array<AstNode *> const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if a new package is present
|
// Returns true if a new package is present
|
||||||
bool collect_file_decls(CheckerContext *ctx, Array<AstNode *> const &decls);
|
bool collect_file_decls(CheckerContext *ctx, Array<Ast *> const &decls);
|
||||||
bool collect_file_decls_from_when_stmt(CheckerContext *ctx, AstNodeWhenStmt *ws);
|
bool collect_file_decls_from_when_stmt(CheckerContext *ctx, AstWhenStmt *ws);
|
||||||
|
|
||||||
bool collect_when_stmt_from_file(CheckerContext *ctx, AstNodeWhenStmt *ws) {
|
bool collect_when_stmt_from_file(CheckerContext *ctx, AstWhenStmt *ws) {
|
||||||
Operand operand = {Addressing_Invalid};
|
Operand operand = {Addressing_Invalid};
|
||||||
if (!ws->is_cond_determined) {
|
if (!ws->is_cond_determined) {
|
||||||
check_expr(ctx, &operand, ws->cond);
|
check_expr(ctx, &operand, ws->cond);
|
||||||
@@ -2708,16 +2708,16 @@ bool collect_when_stmt_from_file(CheckerContext *ctx, AstNodeWhenStmt *ws) {
|
|||||||
ws->determined_cond = operand.value.kind == ExactValue_Bool && operand.value.value_bool;
|
ws->determined_cond = operand.value.kind == ExactValue_Bool && operand.value.value_bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ws->body == nullptr || ws->body->kind != AstNode_BlockStmt) {
|
if (ws->body == nullptr || ws->body->kind != Ast_BlockStmt) {
|
||||||
error(ws->cond, "Invalid body for 'when' statement");
|
error(ws->cond, "Invalid body for 'when' statement");
|
||||||
} else {
|
} else {
|
||||||
if (ws->determined_cond) {
|
if (ws->determined_cond) {
|
||||||
return collect_checked_packages_from_decl_list(ctx->checker, ws->body->BlockStmt.stmts);
|
return collect_checked_packages_from_decl_list(ctx->checker, ws->body->BlockStmt.stmts);
|
||||||
} else if (ws->else_stmt) {
|
} else if (ws->else_stmt) {
|
||||||
switch (ws->else_stmt->kind) {
|
switch (ws->else_stmt->kind) {
|
||||||
case AstNode_BlockStmt:
|
case Ast_BlockStmt:
|
||||||
return collect_checked_packages_from_decl_list(ctx->checker, ws->else_stmt->BlockStmt.stmts);
|
return collect_checked_packages_from_decl_list(ctx->checker, ws->else_stmt->BlockStmt.stmts);
|
||||||
case AstNode_WhenStmt:
|
case Ast_WhenStmt:
|
||||||
return collect_when_stmt_from_file(ctx, &ws->else_stmt->WhenStmt);
|
return collect_when_stmt_from_file(ctx, &ws->else_stmt->WhenStmt);
|
||||||
default:
|
default:
|
||||||
error(ws->else_stmt, "Invalid 'else' statement in 'when' statement");
|
error(ws->else_stmt, "Invalid 'else' statement in 'when' statement");
|
||||||
@@ -2729,7 +2729,7 @@ bool collect_when_stmt_from_file(CheckerContext *ctx, AstNodeWhenStmt *ws) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool collect_file_decls_from_when_stmt(CheckerContext *ctx, AstNodeWhenStmt *ws) {
|
bool collect_file_decls_from_when_stmt(CheckerContext *ctx, AstWhenStmt *ws) {
|
||||||
Operand operand = {Addressing_Invalid};
|
Operand operand = {Addressing_Invalid};
|
||||||
if (!ws->is_cond_determined) {
|
if (!ws->is_cond_determined) {
|
||||||
check_expr(ctx, &operand, ws->cond);
|
check_expr(ctx, &operand, ws->cond);
|
||||||
@@ -2744,16 +2744,16 @@ bool collect_file_decls_from_when_stmt(CheckerContext *ctx, AstNodeWhenStmt *ws)
|
|||||||
ws->determined_cond = operand.value.kind == ExactValue_Bool && operand.value.value_bool;
|
ws->determined_cond = operand.value.kind == ExactValue_Bool && operand.value.value_bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ws->body == nullptr || ws->body->kind != AstNode_BlockStmt) {
|
if (ws->body == nullptr || ws->body->kind != Ast_BlockStmt) {
|
||||||
error(ws->cond, "Invalid body for 'when' statement");
|
error(ws->cond, "Invalid body for 'when' statement");
|
||||||
} else {
|
} else {
|
||||||
if (ws->determined_cond) {
|
if (ws->determined_cond) {
|
||||||
return collect_file_decls(ctx, ws->body->BlockStmt.stmts);
|
return collect_file_decls(ctx, ws->body->BlockStmt.stmts);
|
||||||
} else if (ws->else_stmt) {
|
} else if (ws->else_stmt) {
|
||||||
switch (ws->else_stmt->kind) {
|
switch (ws->else_stmt->kind) {
|
||||||
case AstNode_BlockStmt:
|
case Ast_BlockStmt:
|
||||||
return collect_file_decls(ctx, ws->else_stmt->BlockStmt.stmts);
|
return collect_file_decls(ctx, ws->else_stmt->BlockStmt.stmts);
|
||||||
case AstNode_WhenStmt:
|
case Ast_WhenStmt:
|
||||||
return collect_file_decls_from_when_stmt(ctx, &ws->else_stmt->WhenStmt);
|
return collect_file_decls_from_when_stmt(ctx, &ws->else_stmt->WhenStmt);
|
||||||
default:
|
default:
|
||||||
error(ws->else_stmt, "Invalid 'else' statement in 'when' statement");
|
error(ws->else_stmt, "Invalid 'else' statement in 'when' statement");
|
||||||
@@ -2765,7 +2765,7 @@ bool collect_file_decls_from_when_stmt(CheckerContext *ctx, AstNodeWhenStmt *ws)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool collect_file_decls(CheckerContext *ctx, Array<AstNode *> const &decls) {
|
bool collect_file_decls(CheckerContext *ctx, Array<Ast *> const &decls) {
|
||||||
GB_ASSERT(ctx->scope->is_file);
|
GB_ASSERT(ctx->scope->is_file);
|
||||||
|
|
||||||
if (collect_checked_packages_from_decl_list(ctx->checker, decls)) {
|
if (collect_checked_packages_from_decl_list(ctx->checker, decls)) {
|
||||||
@@ -2773,7 +2773,7 @@ bool collect_file_decls(CheckerContext *ctx, Array<AstNode *> const &decls) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for_array(i, decls) {
|
for_array(i, decls) {
|
||||||
AstNode *decl = decls[i];
|
Ast *decl = decls[i];
|
||||||
switch (decl->kind) {
|
switch (decl->kind) {
|
||||||
case_ast_node(vd, ValueDecl, decl);
|
case_ast_node(vd, ValueDecl, decl);
|
||||||
check_collect_value_decl(ctx, decl);
|
check_collect_value_decl(ctx, decl);
|
||||||
@@ -2814,7 +2814,7 @@ bool collect_file_decls(CheckerContext *ctx, Array<AstNode *> const &decls) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(ce, CallExpr, decl);
|
case_ast_node(ce, CallExpr, decl);
|
||||||
if (ce->proc->kind == AstNode_BasicDirective) {
|
if (ce->proc->kind == Ast_BasicDirective) {
|
||||||
Operand o = {};
|
Operand o = {};
|
||||||
check_expr(ctx, &o, decl);
|
check_expr(ctx, &o, decl);
|
||||||
}
|
}
|
||||||
@@ -2975,11 +2975,11 @@ void check_import_entities(Checker *c) {
|
|||||||
|
|
||||||
add_curr_ast_file(&ctx, f);
|
add_curr_ast_file(&ctx, f);
|
||||||
for_array(j, f->scope->delayed_imports) {
|
for_array(j, f->scope->delayed_imports) {
|
||||||
AstNode *decl = f->scope->delayed_imports[j];
|
Ast *decl = f->scope->delayed_imports[j];
|
||||||
check_add_import_decl(&ctx, decl);
|
check_add_import_decl(&ctx, decl);
|
||||||
}
|
}
|
||||||
for_array(j, f->scope->delayed_directives) {
|
for_array(j, f->scope->delayed_directives) {
|
||||||
AstNode *expr = f->scope->delayed_directives[j];
|
Ast *expr = f->scope->delayed_directives[j];
|
||||||
Operand o = {};
|
Operand o = {};
|
||||||
check_expr(&ctx, &o, expr);
|
check_expr(&ctx, &o, expr);
|
||||||
}
|
}
|
||||||
@@ -3139,7 +3139,7 @@ void check_proc_info(Checker *c, ProcInfo pi) {
|
|||||||
if (pt->is_polymorphic && !pt->is_poly_specialized) {
|
if (pt->is_polymorphic && !pt->is_poly_specialized) {
|
||||||
Token token = pi.token;
|
Token token = pi.token;
|
||||||
if (pi.poly_def_node != nullptr) {
|
if (pi.poly_def_node != nullptr) {
|
||||||
token = ast_node_token(pi.poly_def_node);
|
token = ast_token(pi.poly_def_node);
|
||||||
}
|
}
|
||||||
error(token, "Unspecialized polymorphic procedure '%.*s'", LIT(name));
|
error(token, "Unspecialized polymorphic procedure '%.*s'", LIT(name));
|
||||||
return;
|
return;
|
||||||
@@ -3260,7 +3260,7 @@ void check_parsed_files(Checker *c) {
|
|||||||
for_array(i, c->info.untyped.entries) {
|
for_array(i, c->info.untyped.entries) {
|
||||||
auto *entry = &c->info.untyped.entries[i];
|
auto *entry = &c->info.untyped.entries[i];
|
||||||
HashKey key = entry->key;
|
HashKey key = entry->key;
|
||||||
AstNode *expr = cast(AstNode *)key.ptr;
|
Ast *expr = cast(Ast *)key.ptr;
|
||||||
ExprInfo *info = &entry->value;
|
ExprInfo *info = &entry->value;
|
||||||
if (info != nullptr && expr != nullptr) {
|
if (info != nullptr && expr != nullptr) {
|
||||||
if (is_type_typed(info->type)) {
|
if (is_type_typed(info->type)) {
|
||||||
|
|||||||
+40
-40
@@ -167,7 +167,7 @@ struct Operand {
|
|||||||
AddressingMode mode;
|
AddressingMode mode;
|
||||||
Type * type;
|
Type * type;
|
||||||
ExactValue value;
|
ExactValue value;
|
||||||
AstNode * expr;
|
Ast * expr;
|
||||||
BuiltinProcId builtin_id;
|
BuiltinProcId builtin_id;
|
||||||
Entity * proc_group;
|
Entity * proc_group;
|
||||||
};
|
};
|
||||||
@@ -175,7 +175,7 @@ struct Operand {
|
|||||||
|
|
||||||
struct BlockLabel {
|
struct BlockLabel {
|
||||||
String name;
|
String name;
|
||||||
AstNode *label; // AstNode_Label;
|
Ast *label; // Ast_Label;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AttributeContext {
|
struct AttributeContext {
|
||||||
@@ -192,10 +192,10 @@ AttributeContext make_attribute_context(String link_prefix) {
|
|||||||
return ac;
|
return ac;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DECL_ATTRIBUTE_PROC(_name) bool _name(CheckerContext *c, AstNode *elem, String name, ExactValue value, AttributeContext *ac)
|
#define DECL_ATTRIBUTE_PROC(_name) bool _name(CheckerContext *c, Ast *elem, String name, ExactValue value, AttributeContext *ac)
|
||||||
typedef DECL_ATTRIBUTE_PROC(DeclAttributeProc);
|
typedef DECL_ATTRIBUTE_PROC(DeclAttributeProc);
|
||||||
|
|
||||||
void check_decl_attributes(CheckerContext *c, Array<AstNode *> const &attributes, DeclAttributeProc *proc, AttributeContext *ac);
|
void check_decl_attributes(CheckerContext *c, Array<Ast *> const &attributes, DeclAttributeProc *proc, AttributeContext *ac);
|
||||||
|
|
||||||
|
|
||||||
// DeclInfo is used to store information of certain declarations to allow for "any order" usage
|
// DeclInfo is used to store information of certain declarations to allow for "any order" usage
|
||||||
@@ -206,11 +206,11 @@ struct DeclInfo {
|
|||||||
Entity ** entities;
|
Entity ** entities;
|
||||||
isize entity_count;
|
isize entity_count;
|
||||||
|
|
||||||
AstNode * type_expr;
|
Ast * type_expr;
|
||||||
AstNode * init_expr;
|
Ast * init_expr;
|
||||||
Array<AstNode *> init_expr_list;
|
Array<Ast *> init_expr_list;
|
||||||
Array<AstNode *> attributes;
|
Array<Ast *> attributes;
|
||||||
AstNode * proc_lit; // AstNode_ProcLit
|
Ast * proc_lit; // Ast_ProcLit
|
||||||
Type * gen_proc_type; // Precalculated
|
Type * gen_proc_type; // Precalculated
|
||||||
|
|
||||||
PtrSet<Entity *> deps;
|
PtrSet<Entity *> deps;
|
||||||
@@ -224,16 +224,16 @@ struct ProcInfo {
|
|||||||
Token token;
|
Token token;
|
||||||
DeclInfo *decl;
|
DeclInfo *decl;
|
||||||
Type * type; // Type_Procedure
|
Type * type; // Type_Procedure
|
||||||
AstNode * body; // AstNode_BlockStmt
|
Ast * body; // Ast_BlockStmt
|
||||||
u64 tags;
|
u64 tags;
|
||||||
bool generated_from_polymorphic;
|
bool generated_from_polymorphic;
|
||||||
AstNode * poly_def_node;
|
Ast * poly_def_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct Scope {
|
struct Scope {
|
||||||
AstNode * node;
|
Ast * node;
|
||||||
Scope * parent;
|
Scope * parent;
|
||||||
Scope * prev, *next;
|
Scope * prev, *next;
|
||||||
Scope * first_child;
|
Scope * first_child;
|
||||||
@@ -242,8 +242,8 @@ struct Scope {
|
|||||||
PtrSet<Entity *> implicit;
|
PtrSet<Entity *> implicit;
|
||||||
// Scope * shared;
|
// Scope * shared;
|
||||||
|
|
||||||
Array<AstNode *> delayed_directives;
|
Array<Ast *> delayed_directives;
|
||||||
Array<AstNode *> delayed_imports;
|
Array<Ast *> delayed_imports;
|
||||||
PtrSet<Scope *> imported;
|
PtrSet<Scope *> imported;
|
||||||
bool is_proc;
|
bool is_proc;
|
||||||
bool is_global;
|
bool is_global;
|
||||||
@@ -290,7 +290,7 @@ struct ImportGraphNode {
|
|||||||
|
|
||||||
|
|
||||||
struct ForeignContext {
|
struct ForeignContext {
|
||||||
AstNode * curr_library;
|
Ast * curr_library;
|
||||||
ProcCallingConvention default_cc;
|
ProcCallingConvention default_cc;
|
||||||
String link_prefix;
|
String link_prefix;
|
||||||
bool in_export;
|
bool in_export;
|
||||||
@@ -301,8 +301,8 @@ typedef Array<Type *> CheckerPolyPath;
|
|||||||
|
|
||||||
// CheckerInfo stores all the symbol information for a type-checked program
|
// CheckerInfo stores all the symbol information for a type-checked program
|
||||||
struct CheckerInfo {
|
struct CheckerInfo {
|
||||||
Map<TypeAndValue> types; // Key: AstNode * | Expression -> Type (and value)
|
Map<TypeAndValue> types; // Key: Ast * | Expression -> Type (and value)
|
||||||
Map<ExprInfo> untyped; // Key: AstNode * | Expression -> ExprInfo
|
Map<ExprInfo> untyped; // Key: Ast * | Expression -> ExprInfo
|
||||||
Map<AstFile *> files; // Key: String (full path)
|
Map<AstFile *> files; // Key: String (full path)
|
||||||
Map<AstPackage *> packages; // Key: String (full path)
|
Map<AstPackage *> packages; // Key: String (full path)
|
||||||
Map<Entity *> foreigns; // Key: String
|
Map<Entity *> foreigns; // Key: String
|
||||||
@@ -310,7 +310,7 @@ struct CheckerInfo {
|
|||||||
Array<Entity *> entities;
|
Array<Entity *> entities;
|
||||||
Array<DeclInfo *> variable_init_order;
|
Array<DeclInfo *> variable_init_order;
|
||||||
|
|
||||||
Map<Array<Entity *> > gen_procs; // Key: AstNode * | Identifier -> Entity
|
Map<Array<Entity *> > gen_procs; // Key: Ast * | Identifier -> Entity
|
||||||
Map<Array<Entity *> > gen_types; // Key: Type *
|
Map<Array<Entity *> > gen_types; // Key: Type *
|
||||||
|
|
||||||
Array<Type *> type_info_types;
|
Array<Type *> type_info_types;
|
||||||
@@ -368,7 +368,7 @@ struct Checker {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
HashKey hash_node (AstNode *node) { return hash_pointer(node); }
|
HashKey hash_node (Ast *node) { return hash_pointer(node); }
|
||||||
HashKey hash_ast_file (AstFile *file) { return hash_pointer(file); }
|
HashKey hash_ast_file (AstFile *file) { return hash_pointer(file); }
|
||||||
HashKey hash_entity (Entity *e) { return hash_pointer(e); }
|
HashKey hash_entity (Entity *e) { return hash_pointer(e); }
|
||||||
HashKey hash_type (Type *t) { return hash_pointer(t); }
|
HashKey hash_type (Type *t) { return hash_pointer(t); }
|
||||||
@@ -377,19 +377,19 @@ HashKey hash_decl_info(DeclInfo *decl) { return hash_pointer(decl); }
|
|||||||
|
|
||||||
|
|
||||||
// CheckerInfo API
|
// CheckerInfo API
|
||||||
TypeAndValue type_and_value_of_expr (CheckerInfo *i, AstNode *expr);
|
TypeAndValue type_and_value_of_expr (CheckerInfo *i, Ast *expr);
|
||||||
Type * type_of_expr (CheckerInfo *i, AstNode *expr);
|
Type * type_of_expr (CheckerInfo *i, Ast *expr);
|
||||||
Entity * entity_of_ident (AstNode *identifier);
|
Entity * entity_of_ident (Ast *identifier);
|
||||||
Entity * implicit_entity_of_node(CheckerInfo *i, AstNode *clause);
|
Entity * implicit_entity_of_node(CheckerInfo *i, Ast *clause);
|
||||||
Scope * scope_of_node (AstNode *node);
|
Scope * scope_of_node (Ast *node);
|
||||||
DeclInfo * decl_info_of_ident (AstNode *ident);
|
DeclInfo * decl_info_of_ident (Ast *ident);
|
||||||
DeclInfo * decl_info_of_entity (Entity * e);
|
DeclInfo * decl_info_of_entity (Entity * e);
|
||||||
AstFile * ast_file_of_filename (CheckerInfo *i, String filename);
|
AstFile * ast_file_of_filename (CheckerInfo *i, String filename);
|
||||||
// IMPORTANT: Only to use once checking is done
|
// IMPORTANT: Only to use once checking is done
|
||||||
isize type_info_index (CheckerInfo *i, Type * type, bool error_on_failure = true);
|
isize type_info_index (CheckerInfo *i, Type * type, bool error_on_failure = true);
|
||||||
|
|
||||||
// Will return nullptr if not found
|
// Will return nullptr if not found
|
||||||
Entity *entity_of_node(CheckerInfo *i, AstNode *expr);
|
Entity *entity_of_node(CheckerInfo *i, Ast *expr);
|
||||||
|
|
||||||
|
|
||||||
Entity *scope_lookup_current(Scope *s, String name);
|
Entity *scope_lookup_current(Scope *s, String name);
|
||||||
@@ -398,24 +398,24 @@ void scope_lookup_parent (Scope *s, String name, Scope **scope_, Entity **ent
|
|||||||
Entity *scope_insert (Scope *s, Entity *entity);
|
Entity *scope_insert (Scope *s, Entity *entity);
|
||||||
|
|
||||||
|
|
||||||
ExprInfo *check_get_expr_info (CheckerInfo *i, AstNode *expr);
|
ExprInfo *check_get_expr_info (CheckerInfo *i, Ast *expr);
|
||||||
void check_set_expr_info (CheckerInfo *i, AstNode *expr, ExprInfo info);
|
void check_set_expr_info (CheckerInfo *i, Ast *expr, ExprInfo info);
|
||||||
void check_remove_expr_info (CheckerInfo *i, AstNode *expr);
|
void check_remove_expr_info (CheckerInfo *i, Ast *expr);
|
||||||
void add_untyped (CheckerInfo *i, AstNode *expression, bool lhs, AddressingMode mode, Type *basic_type, ExactValue value);
|
void add_untyped (CheckerInfo *i, Ast *expression, bool lhs, AddressingMode mode, Type *basic_type, ExactValue value);
|
||||||
void add_type_and_value (CheckerInfo *i, AstNode *expression, AddressingMode mode, Type *type, ExactValue value);
|
void add_type_and_value (CheckerInfo *i, Ast *expression, AddressingMode mode, Type *type, ExactValue value);
|
||||||
void add_entity_use (CheckerContext *c, AstNode *identifier, Entity *entity);
|
void add_entity_use (CheckerContext *c, Ast *identifier, Entity *entity);
|
||||||
void add_implicit_entity (CheckerContext *c, AstNode *node, Entity *e);
|
void add_implicit_entity (CheckerContext *c, Ast *node, Entity *e);
|
||||||
void add_entity_and_decl_info(CheckerContext *c, AstNode *identifier, Entity *e, DeclInfo *d);
|
void add_entity_and_decl_info(CheckerContext *c, Ast *identifier, Entity *e, DeclInfo *d);
|
||||||
void add_type_info_type (CheckerContext *c, Type *t);
|
void add_type_info_type (CheckerContext *c, Type *t);
|
||||||
|
|
||||||
void check_add_import_decl(CheckerContext *c, AstNode *decl);
|
void check_add_import_decl(CheckerContext *c, Ast *decl);
|
||||||
void check_add_foreign_import_decl(CheckerContext *c, AstNode *decl);
|
void check_add_foreign_import_decl(CheckerContext *c, Ast *decl);
|
||||||
|
|
||||||
|
|
||||||
bool check_arity_match(CheckerContext *c, AstNodeValueDecl *vd, bool is_global = false);
|
bool check_arity_match(CheckerContext *c, AstValueDecl *vd, bool is_global = false);
|
||||||
void check_collect_entities(CheckerContext *c, Array<AstNode *> const &nodes);
|
void check_collect_entities(CheckerContext *c, Array<Ast *> const &nodes);
|
||||||
void check_collect_entities_from_when_stmt(CheckerContext *c, AstNodeWhenStmt *ws);
|
void check_collect_entities_from_when_stmt(CheckerContext *c, AstWhenStmt *ws);
|
||||||
void check_delayed_file_import_entity(CheckerContext *c, AstNode *decl);
|
void check_delayed_file_import_entity(CheckerContext *c, Ast *decl);
|
||||||
|
|
||||||
CheckerTypePath *new_checker_type_path();
|
CheckerTypePath *new_checker_type_path();
|
||||||
void destroy_checker_type_path(CheckerTypePath *tp);
|
void destroy_checker_type_path(CheckerTypePath *tp);
|
||||||
|
|||||||
+7
-7
@@ -1,6 +1,6 @@
|
|||||||
// Generates Documentation
|
// Generates Documentation
|
||||||
|
|
||||||
gbString expr_to_string(AstNode *expression);
|
gbString expr_to_string(Ast *expression);
|
||||||
|
|
||||||
String alloc_comment_group_string(gbAllocator a, CommentGroup g) {
|
String alloc_comment_group_string(gbAllocator a, CommentGroup g) {
|
||||||
isize len = 0;
|
isize len = 0;
|
||||||
@@ -33,9 +33,9 @@ String alloc_comment_group_string(gbAllocator a, CommentGroup g) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
void print_type_spec(AstNode *spec) {
|
void print_type_spec(Ast *spec) {
|
||||||
ast_node(ts, TypeSpec, spec);
|
ast_node(ts, TypeSpec, spec);
|
||||||
GB_ASSERT(ts->name->kind == AstNode_Ident);
|
GB_ASSERT(ts->name->kind == Ast_Ident);
|
||||||
String name = ts->name->Ident.string;
|
String name = ts->name->Ident.string;
|
||||||
if (name.len == 0) {
|
if (name.len == 0) {
|
||||||
return;
|
return;
|
||||||
@@ -46,8 +46,8 @@ void print_type_spec(AstNode *spec) {
|
|||||||
gb_printf("type %.*s\n", LIT(name));
|
gb_printf("type %.*s\n", LIT(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_proc_decl(AstNodeProcDecl *pd) {
|
void print_proc_decl(AstProcDecl *pd) {
|
||||||
GB_ASSERT(pd->name->kind == AstNode_Ident);
|
GB_ASSERT(pd->name->kind == Ast_Ident);
|
||||||
String name = pd->name->Ident.string;
|
String name = pd->name->Ident.string;
|
||||||
if (name.len == 0) {
|
if (name.len == 0) {
|
||||||
return;
|
return;
|
||||||
@@ -89,7 +89,7 @@ void print_proc_decl(AstNodeProcDecl *pd) {
|
|||||||
gb_printf("\n\n");
|
gb_printf("\n\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void print_declaration(AstNode *decl) {
|
void print_declaration(Ast *decl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_documentation(Parser *parser) {
|
void generate_documentation(Parser *parser) {
|
||||||
@@ -100,7 +100,7 @@ void generate_documentation(Parser *parser) {
|
|||||||
// gb_printf("%.*s\n", LIT(fullpath));
|
// gb_printf("%.*s\n", LIT(fullpath));
|
||||||
|
|
||||||
// for_array(decl_index, file->decls) {
|
// for_array(decl_index, file->decls) {
|
||||||
// AstNode *decl = file->decls[decl_index];
|
// Ast *decl = file->decls[decl_index];
|
||||||
// print_declaration(decl);
|
// print_declaration(decl);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|||||||
+6
-6
@@ -65,14 +65,14 @@ struct Entity {
|
|||||||
Token token;
|
Token token;
|
||||||
Scope * scope;
|
Scope * scope;
|
||||||
Type * type;
|
Type * type;
|
||||||
AstNode * identifier; // Can be nullptr
|
Ast * identifier; // Can be nullptr
|
||||||
DeclInfo * decl_info;
|
DeclInfo * decl_info;
|
||||||
DeclInfo * parent_proc_decl; // nullptr if in file/global scope
|
DeclInfo * parent_proc_decl; // nullptr if in file/global scope
|
||||||
AstPackage *pkg;
|
AstPackage *pkg;
|
||||||
|
|
||||||
// TODO(bill): Cleanup how `using` works for entities
|
// TODO(bill): Cleanup how `using` works for entities
|
||||||
Entity * using_parent;
|
Entity * using_parent;
|
||||||
AstNode * using_expr;
|
Ast * using_expr;
|
||||||
|
|
||||||
isize order_in_src;
|
isize order_in_src;
|
||||||
String deprecated_message;
|
String deprecated_message;
|
||||||
@@ -87,7 +87,7 @@ struct Entity {
|
|||||||
ExactValue default_value;
|
ExactValue default_value;
|
||||||
String thread_local_model;
|
String thread_local_model;
|
||||||
Entity * foreign_library;
|
Entity * foreign_library;
|
||||||
AstNode * foreign_library_ident;
|
Ast * foreign_library_ident;
|
||||||
String link_name;
|
String link_name;
|
||||||
String link_prefix;
|
String link_prefix;
|
||||||
bool is_foreign;
|
bool is_foreign;
|
||||||
@@ -106,7 +106,7 @@ struct Entity {
|
|||||||
struct {
|
struct {
|
||||||
u64 tags;
|
u64 tags;
|
||||||
Entity * foreign_library;
|
Entity * foreign_library;
|
||||||
AstNode * foreign_library_ident;
|
Ast * foreign_library_ident;
|
||||||
String link_name;
|
String link_name;
|
||||||
String link_prefix;
|
String link_prefix;
|
||||||
bool is_foreign;
|
bool is_foreign;
|
||||||
@@ -130,7 +130,7 @@ struct Entity {
|
|||||||
i32 Nil;
|
i32 Nil;
|
||||||
struct {
|
struct {
|
||||||
String name;
|
String name;
|
||||||
AstNode *node;
|
Ast *node;
|
||||||
} Label;
|
} Label;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -295,7 +295,7 @@ Entity *alloc_entity_nil(String name, Type *type) {
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity *alloc_entity_label(Scope *scope, Token token, Type *type, AstNode *node) {
|
Entity *alloc_entity_label(Scope *scope, Token token, Type *type, Ast *node) {
|
||||||
Entity *entity = alloc_entity(Entity_Label, scope, token, type);
|
Entity *entity = alloc_entity(Entity_Label, scope, token, type);
|
||||||
entity->Label.node = node;
|
entity->Label.node = node;
|
||||||
entity->state = EntityState_Resolved;
|
entity->state = EntityState_Resolved;
|
||||||
|
|||||||
+5
-5
@@ -3,7 +3,7 @@
|
|||||||
// TODO(bill): Big numbers
|
// TODO(bill): Big numbers
|
||||||
// IMPORTANT TODO(bill): This needs to be completely fixed!!!!!!!!
|
// IMPORTANT TODO(bill): This needs to be completely fixed!!!!!!!!
|
||||||
|
|
||||||
struct AstNode;
|
struct Ast;
|
||||||
struct HashKey;
|
struct HashKey;
|
||||||
struct Type;
|
struct Type;
|
||||||
struct Entity;
|
struct Entity;
|
||||||
@@ -37,8 +37,8 @@ struct ExactValue {
|
|||||||
f64 value_float;
|
f64 value_float;
|
||||||
i64 value_pointer;
|
i64 value_pointer;
|
||||||
Complex128 value_complex;
|
Complex128 value_complex;
|
||||||
AstNode * value_compound;
|
Ast * value_compound;
|
||||||
AstNode * value_procedure;
|
Ast * value_procedure;
|
||||||
Entity * value_entity;
|
Entity * value_entity;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -73,7 +73,7 @@ HashKey hash_exact_value(ExactValue v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ExactValue exact_value_compound(AstNode *node) {
|
ExactValue exact_value_compound(Ast *node) {
|
||||||
ExactValue result = {ExactValue_Compound};
|
ExactValue result = {ExactValue_Compound};
|
||||||
result.value_compound = node;
|
result.value_compound = node;
|
||||||
return result;
|
return result;
|
||||||
@@ -123,7 +123,7 @@ ExactValue exact_value_pointer(i64 ptr) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExactValue exact_value_procedure(AstNode *node) {
|
ExactValue exact_value_procedure(Ast *node) {
|
||||||
ExactValue result = {ExactValue_Procedure};
|
ExactValue result = {ExactValue_Procedure};
|
||||||
result.value_procedure = node;
|
result.value_procedure = node;
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
+133
-133
@@ -24,7 +24,7 @@ struct irModule {
|
|||||||
Map<irValue *> members; // Key: String
|
Map<irValue *> members; // Key: String
|
||||||
Map<String> entity_names; // Key: Entity * of the typename
|
Map<String> entity_names; // Key: Entity * of the typename
|
||||||
Map<irDebugInfo *> debug_info; // Key: Unique pointer
|
Map<irDebugInfo *> debug_info; // Key: Unique pointer
|
||||||
Map<irValue *> anonymous_proc_lits; // Key: AstNode *
|
Map<irValue *> anonymous_proc_lits; // Key: Ast *
|
||||||
|
|
||||||
irDebugInfo * debug_compile_unit;
|
irDebugInfo * debug_compile_unit;
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ struct irBlock {
|
|||||||
i32 index;
|
i32 index;
|
||||||
String label;
|
String label;
|
||||||
irProcedure *proc;
|
irProcedure *proc;
|
||||||
AstNode * node; // Can be nullptr
|
Ast * node; // Can be nullptr
|
||||||
Scope * scope;
|
Scope * scope;
|
||||||
isize scope_index;
|
isize scope_index;
|
||||||
irDomNode dom;
|
irDomNode dom;
|
||||||
@@ -95,7 +95,7 @@ struct irDefer {
|
|||||||
isize scope_index;
|
isize scope_index;
|
||||||
irBlock * block;
|
irBlock * block;
|
||||||
union {
|
union {
|
||||||
AstNode *stmt;
|
Ast *stmt;
|
||||||
// NOTE(bill): 'instr' will be copied every time to create a new one
|
// NOTE(bill): 'instr' will be copied every time to create a new one
|
||||||
irValue *instr;
|
irValue *instr;
|
||||||
};
|
};
|
||||||
@@ -103,7 +103,7 @@ struct irDefer {
|
|||||||
|
|
||||||
|
|
||||||
struct irBranchBlocks {
|
struct irBranchBlocks {
|
||||||
AstNode *label;
|
Ast *label;
|
||||||
irBlock *break_;
|
irBlock *break_;
|
||||||
irBlock *continue_;
|
irBlock *continue_;
|
||||||
};
|
};
|
||||||
@@ -122,8 +122,8 @@ struct irProcedure {
|
|||||||
irModule * module;
|
irModule * module;
|
||||||
String name;
|
String name;
|
||||||
Type * type;
|
Type * type;
|
||||||
AstNode * type_expr;
|
Ast * type_expr;
|
||||||
AstNode * body;
|
Ast * body;
|
||||||
u64 tags;
|
u64 tags;
|
||||||
ProcInlining inlining;
|
ProcInlining inlining;
|
||||||
bool is_foreign;
|
bool is_foreign;
|
||||||
@@ -244,7 +244,7 @@ struct irProcedure {
|
|||||||
IR_INSTR_KIND(StartupRuntime, i32) \
|
IR_INSTR_KIND(StartupRuntime, i32) \
|
||||||
IR_INSTR_KIND(DebugDeclare, struct { \
|
IR_INSTR_KIND(DebugDeclare, struct { \
|
||||||
irDebugInfo *scope; \
|
irDebugInfo *scope; \
|
||||||
AstNode * expr; \
|
Ast * expr; \
|
||||||
Entity * entity; \
|
Entity * entity; \
|
||||||
bool is_addr; \
|
bool is_addr; \
|
||||||
irValue * value; \
|
irValue * value; \
|
||||||
@@ -758,7 +758,7 @@ Array<irValue *> *ir_value_referrers(irValue *v) {
|
|||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void ir_module_add_value (irModule *m, Entity *e, irValue *v);
|
void ir_module_add_value (irModule *m, Entity *e, irValue *v);
|
||||||
void ir_emit_zero_init (irProcedure *p, irValue *address, AstNode *expr);
|
void ir_emit_zero_init (irProcedure *p, irValue *address, Ast *expr);
|
||||||
irValue *ir_emit_comment (irProcedure *p, String text);
|
irValue *ir_emit_comment (irProcedure *p, String text);
|
||||||
irValue *ir_emit_store (irProcedure *p, irValue *address, irValue *value);
|
irValue *ir_emit_store (irProcedure *p, irValue *address, irValue *value);
|
||||||
irValue *ir_emit_load (irProcedure *p, irValue *address);
|
irValue *ir_emit_load (irProcedure *p, irValue *address);
|
||||||
@@ -766,11 +766,11 @@ void ir_emit_jump (irProcedure *proc, irBlock *block);
|
|||||||
irValue *ir_emit_conv (irProcedure *proc, irValue *value, Type *t);
|
irValue *ir_emit_conv (irProcedure *proc, irValue *value, Type *t);
|
||||||
irValue *ir_type_info (irProcedure *proc, Type *type);
|
irValue *ir_type_info (irProcedure *proc, Type *type);
|
||||||
irValue *ir_typeid (irModule *m, Type *type);
|
irValue *ir_typeid (irModule *m, Type *type);
|
||||||
irValue *ir_build_expr (irProcedure *proc, AstNode *expr);
|
irValue *ir_build_expr (irProcedure *proc, Ast *expr);
|
||||||
void ir_build_stmt (irProcedure *proc, AstNode *node);
|
void ir_build_stmt (irProcedure *proc, Ast *node);
|
||||||
irValue *ir_build_cond (irProcedure *proc, AstNode *cond, irBlock *true_block, irBlock *false_block);
|
irValue *ir_build_cond (irProcedure *proc, Ast *cond, irBlock *true_block, irBlock *false_block);
|
||||||
void ir_build_defer_stmt (irProcedure *proc, irDefer d);
|
void ir_build_defer_stmt (irProcedure *proc, irDefer d);
|
||||||
irAddr ir_build_addr (irProcedure *proc, AstNode *expr);
|
irAddr ir_build_addr (irProcedure *proc, Ast *expr);
|
||||||
void ir_build_proc (irValue *value, irProcedure *parent);
|
void ir_build_proc (irValue *value, irProcedure *parent);
|
||||||
void ir_gen_global_type_name(irModule *m, Entity *e, String name);
|
void ir_gen_global_type_name(irModule *m, Entity *e, String name);
|
||||||
irValue *ir_get_type_info_ptr (irProcedure *proc, Type *type);
|
irValue *ir_get_type_info_ptr (irProcedure *proc, Type *type);
|
||||||
@@ -1081,7 +1081,7 @@ irValue *ir_instr_comment(irProcedure *p, String text) {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_instr_debug_declare(irProcedure *p, irDebugInfo *scope, AstNode *expr, Entity *entity, bool is_addr, irValue *value) {
|
irValue *ir_instr_debug_declare(irProcedure *p, irDebugInfo *scope, Ast *expr, Entity *entity, bool is_addr, irValue *value) {
|
||||||
irValue *v = ir_alloc_instr(p, irInstr_DebugDeclare);
|
irValue *v = ir_alloc_instr(p, irInstr_DebugDeclare);
|
||||||
v->Instr.DebugDeclare.scope = scope;
|
v->Instr.DebugDeclare.scope = scope;
|
||||||
v->Instr.DebugDeclare.expr = expr;
|
v->Instr.DebugDeclare.expr = expr;
|
||||||
@@ -1159,7 +1159,7 @@ irValue *ir_const_string(gbAllocator a, String s) {
|
|||||||
return ir_value_constant(a, t_string, exact_value_string(s));
|
return ir_value_constant(a, t_string, exact_value_string(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_value_procedure(gbAllocator a, irModule *m, Entity *entity, Type *type, AstNode *type_expr, AstNode *body, String name) {
|
irValue *ir_value_procedure(gbAllocator a, irModule *m, Entity *entity, Type *type, Ast *type_expr, Ast *body, String name) {
|
||||||
irValue *v = ir_alloc_value(a, irValue_Proc);
|
irValue *v = ir_alloc_value(a, irValue_Proc);
|
||||||
v->Proc.module = m;
|
v->Proc.module = m;
|
||||||
v->Proc.entity = entity;
|
v->Proc.entity = entity;
|
||||||
@@ -1196,11 +1196,11 @@ irValue *ir_generate_array(irModule *m, Type *elem_type, i64 count, String prefi
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
irBlock *ir_new_block(irProcedure *proc, AstNode *node, char *label) {
|
irBlock *ir_new_block(irProcedure *proc, Ast *node, char *label) {
|
||||||
Scope *scope = nullptr;
|
Scope *scope = nullptr;
|
||||||
if (node != nullptr) {
|
if (node != nullptr) {
|
||||||
scope = scope_of_node(node);
|
scope = scope_of_node(node);
|
||||||
GB_ASSERT_MSG(scope != nullptr, "Block scope not found for %.*s", LIT(ast_node_strings[node->kind]));
|
GB_ASSERT_MSG(scope != nullptr, "Block scope not found for %.*s", LIT(ast_strings[node->kind]));
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *v = ir_alloc_value(proc->module->allocator, irValue_Block);
|
irValue *v = ir_alloc_value(proc->module->allocator, irValue_Block);
|
||||||
@@ -1244,7 +1244,7 @@ void ir_start_block(irProcedure *proc, irBlock *block) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
irDefer ir_add_defer_node(irProcedure *proc, isize scope_index, AstNode *stmt) {
|
irDefer ir_add_defer_node(irProcedure *proc, isize scope_index, Ast *stmt) {
|
||||||
irDefer d = {irDefer_Node};
|
irDefer d = {irDefer_Node};
|
||||||
d.scope_index = scope_index;
|
d.scope_index = scope_index;
|
||||||
d.block = proc->curr_block;
|
d.block = proc->curr_block;
|
||||||
@@ -1355,7 +1355,7 @@ void ir_add_foreign_library_path(irModule *m, Entity *e) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
irValue *ir_add_local(irProcedure *proc, Entity *e, AstNode *expr, bool zero_initialized) {
|
irValue *ir_add_local(irProcedure *proc, Entity *e, Ast *expr, bool zero_initialized) {
|
||||||
irBlock *b = proc->decl_block; // all variables must be in the first block
|
irBlock *b = proc->decl_block; // all variables must be in the first block
|
||||||
irValue *instr = ir_instr_local(proc, e, true);
|
irValue *instr = ir_instr_local(proc, e, true);
|
||||||
instr->Instr.block = b;
|
instr->Instr.block = b;
|
||||||
@@ -1375,7 +1375,7 @@ irValue *ir_add_local(irProcedure *proc, Entity *e, AstNode *expr, bool zero_ini
|
|||||||
return instr;
|
return instr;
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_add_local_for_identifier(irProcedure *proc, AstNode *ident, bool zero_initialized) {
|
irValue *ir_add_local_for_identifier(irProcedure *proc, Ast *ident, bool zero_initialized) {
|
||||||
Entity *e = entity_of_ident(ident);
|
Entity *e = entity_of_ident(ident);
|
||||||
if (e != nullptr) {
|
if (e != nullptr) {
|
||||||
String name = e->token.string;
|
String name = e->token.string;
|
||||||
@@ -1436,7 +1436,7 @@ irValue *ir_add_global_generated(irModule *m, Type *type, irValue *value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
irValue *ir_add_param(irProcedure *proc, Entity *e, AstNode *expr, Type *abi_type) {
|
irValue *ir_add_param(irProcedure *proc, Entity *e, Ast *expr, Type *abi_type) {
|
||||||
irValue *v = ir_value_param(proc->module->allocator, proc, e, abi_type);
|
irValue *v = ir_value_param(proc->module->allocator, proc, e, abi_type);
|
||||||
irValueParam *p = &v->Param;
|
irValueParam *p = &v->Param;
|
||||||
|
|
||||||
@@ -1534,8 +1534,8 @@ irDebugInfo *ir_add_debug_info_proc(irProcedure *proc, Entity *entity, String na
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
irValue *ir_emit_runtime_call (irProcedure *proc, char const *name_, Array<irValue *> args, AstNode *expr = nullptr);
|
irValue *ir_emit_runtime_call (irProcedure *proc, char const *name_, Array<irValue *> args, Ast *expr = nullptr);
|
||||||
irValue *ir_emit_package_call(irProcedure *proc, char const *package_name_, char const *name_, Array<irValue *> args, AstNode *expr = nullptr);
|
irValue *ir_emit_package_call(irProcedure *proc, char const *package_name_, char const *name_, Array<irValue *> args, Ast *expr = nullptr);
|
||||||
|
|
||||||
|
|
||||||
irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value) {
|
irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value) {
|
||||||
@@ -1564,14 +1564,14 @@ irValue *ir_emit_select(irProcedure *p, irValue *cond, irValue *t, irValue *f) {
|
|||||||
return ir_emit(p, ir_instr_select(p, cond, t, f));
|
return ir_emit(p, ir_instr_select(p, cond, t, f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_add_debug_location_to_value(irProcedure *proc, irValue *v, AstNode *e) {
|
void ir_add_debug_location_to_value(irProcedure *proc, irValue *v, Ast *e) {
|
||||||
if (v != nullptr && e != nullptr) {
|
if (v != nullptr && e != nullptr) {
|
||||||
v->loc.debug_scope = proc->debug_scope;
|
v->loc.debug_scope = proc->debug_scope;
|
||||||
v->loc.pos = ast_node_token(e).pos;
|
v->loc.pos = ast_token(e).pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_emit_zero_init(irProcedure *p, irValue *address, AstNode *expr) {
|
void ir_emit_zero_init(irProcedure *p, irValue *address, Ast *expr) {
|
||||||
gbAllocator a = p->module->allocator;
|
gbAllocator a = p->module->allocator;
|
||||||
Type *t = type_deref(ir_type(address));
|
Type *t = type_deref(ir_type(address));
|
||||||
auto args = array_make<irValue *>(a, 2);
|
auto args = array_make<irValue *>(a, 2);
|
||||||
@@ -1702,7 +1702,7 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, Array<irValue *> args) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_emit_runtime_call(irProcedure *proc, char const *name_, Array<irValue *> args, AstNode *expr) {
|
irValue *ir_emit_runtime_call(irProcedure *proc, char const *name_, Array<irValue *> args, Ast *expr) {
|
||||||
String name = make_string_c(cast(char *)name_);
|
String name = make_string_c(cast(char *)name_);
|
||||||
|
|
||||||
AstPackage *p = proc->module->info->runtime_package;
|
AstPackage *p = proc->module->info->runtime_package;
|
||||||
@@ -1714,7 +1714,7 @@ irValue *ir_emit_runtime_call(irProcedure *proc, char const *name_, Array<irValu
|
|||||||
ir_add_debug_location_to_value(proc, call, expr);
|
ir_add_debug_location_to_value(proc, call, expr);
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
irValue *ir_emit_package_call(irProcedure *proc, char const *package_name_, char const *name_, Array<irValue *> args, AstNode *expr) {
|
irValue *ir_emit_package_call(irProcedure *proc, char const *package_name_, char const *name_, Array<irValue *> args, Ast *expr) {
|
||||||
String name = make_string_c(cast(char *)name_);
|
String name = make_string_c(cast(char *)name_);
|
||||||
String package_name = make_string_c(cast(char *)package_name_);
|
String package_name = make_string_c(cast(char *)package_name_);
|
||||||
|
|
||||||
@@ -1921,7 +1921,7 @@ Type *ir_addr_type(irAddr const &addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_emit_source_code_location(irProcedure *proc, String procedure, TokenPos pos);
|
irValue *ir_emit_source_code_location(irProcedure *proc, String procedure, TokenPos pos);
|
||||||
irValue *ir_emit_source_code_location(irProcedure *proc, AstNode *node);
|
irValue *ir_emit_source_code_location(irProcedure *proc, Ast *node);
|
||||||
irValue *ir_emit_ptr_offset(irProcedure *proc, irValue *ptr, irValue *offset);
|
irValue *ir_emit_ptr_offset(irProcedure *proc, irValue *ptr, irValue *offset);
|
||||||
irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *right, Type *type);
|
irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *right, Type *type);
|
||||||
|
|
||||||
@@ -2147,7 +2147,7 @@ irValue *ir_addr_get_ptr(irProcedure *proc, irAddr const &addr) {
|
|||||||
return addr.addr;
|
return addr.addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_build_addr_ptr(irProcedure *proc, AstNode *expr) {
|
irValue *ir_build_addr_ptr(irProcedure *proc, Ast *expr) {
|
||||||
irAddr const &addr = ir_build_addr(proc, expr);
|
irAddr const &addr = ir_build_addr(proc, expr);
|
||||||
return ir_addr_get_ptr(proc, addr);
|
return ir_addr_get_ptr(proc, addr);
|
||||||
}
|
}
|
||||||
@@ -3628,7 +3628,7 @@ irValue *ir_typeid(irModule *m, Type *type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
irValue *ir_emit_logical_binary_expr(irProcedure *proc, TokenKind op, AstNode *left, AstNode *right, Type *type) {
|
irValue *ir_emit_logical_binary_expr(irProcedure *proc, TokenKind op, Ast *left, Ast *right, Type *type) {
|
||||||
irBlock *rhs = ir_new_block(proc, nullptr, "logical.cmp.rhs");
|
irBlock *rhs = ir_new_block(proc, nullptr, "logical.cmp.rhs");
|
||||||
irBlock *done = ir_new_block(proc, nullptr, "logical.cmp.done");
|
irBlock *done = ir_new_block(proc, nullptr, "logical.cmp.done");
|
||||||
|
|
||||||
@@ -3666,7 +3666,7 @@ irValue *ir_emit_logical_binary_expr(irProcedure *proc, TokenKind op, AstNode *l
|
|||||||
return ir_emit(proc, ir_instr_phi(proc, edges, type));
|
return ir_emit(proc, ir_instr_phi(proc, edges, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_emit_logical_binary_expr(irProcedure *proc, AstNode *expr) {
|
irValue *ir_emit_logical_binary_expr(irProcedure *proc, Ast *expr) {
|
||||||
ast_node(be, BinaryExpr, expr);
|
ast_node(be, BinaryExpr, expr);
|
||||||
irBlock *rhs = ir_new_block(proc, nullptr, "logical.cmp.rhs");
|
irBlock *rhs = ir_new_block(proc, nullptr, "logical.cmp.rhs");
|
||||||
irBlock *done = ir_new_block(proc, nullptr, "logical.cmp.done");
|
irBlock *done = ir_new_block(proc, nullptr, "logical.cmp.done");
|
||||||
@@ -3874,8 +3874,8 @@ void ir_mangle_add_sub_type_name(irModule *m, Entity *field, String parent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
irBranchBlocks ir_lookup_branch_blocks(irProcedure *proc, AstNode *ident) {
|
irBranchBlocks ir_lookup_branch_blocks(irProcedure *proc, Ast *ident) {
|
||||||
GB_ASSERT(ident->kind == AstNode_Ident);
|
GB_ASSERT(ident->kind == Ast_Ident);
|
||||||
Entity *e = entity_of_ident(ident);
|
Entity *e = entity_of_ident(ident);
|
||||||
GB_ASSERT(e->kind == Entity_Label);
|
GB_ASSERT(e->kind == Entity_Label);
|
||||||
for_array(i, proc->branch_blocks) {
|
for_array(i, proc->branch_blocks) {
|
||||||
@@ -3891,7 +3891,7 @@ irBranchBlocks ir_lookup_branch_blocks(irProcedure *proc, AstNode *ident) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ir_push_target_list(irProcedure *proc, AstNode *label, irBlock *break_, irBlock *continue_, irBlock *fallthrough_) {
|
void ir_push_target_list(irProcedure *proc, Ast *label, irBlock *break_, irBlock *continue_, irBlock *fallthrough_) {
|
||||||
irTargetList *tl = gb_alloc_item(proc->module->allocator, irTargetList);
|
irTargetList *tl = gb_alloc_item(proc->module->allocator, irTargetList);
|
||||||
tl->prev = proc->target_list;
|
tl->prev = proc->target_list;
|
||||||
tl->break_ = break_;
|
tl->break_ = break_;
|
||||||
@@ -3900,12 +3900,12 @@ void ir_push_target_list(irProcedure *proc, AstNode *label, irBlock *break_, irB
|
|||||||
proc->target_list = tl;
|
proc->target_list = tl;
|
||||||
|
|
||||||
if (label != nullptr) { // Set label blocks
|
if (label != nullptr) { // Set label blocks
|
||||||
GB_ASSERT(label->kind == AstNode_Label);
|
GB_ASSERT(label->kind == Ast_Label);
|
||||||
|
|
||||||
for_array(i, proc->branch_blocks) {
|
for_array(i, proc->branch_blocks) {
|
||||||
irBranchBlocks *b = &proc->branch_blocks[i];
|
irBranchBlocks *b = &proc->branch_blocks[i];
|
||||||
GB_ASSERT(b->label != nullptr && label != nullptr);
|
GB_ASSERT(b->label != nullptr && label != nullptr);
|
||||||
GB_ASSERT(b->label->kind == AstNode_Label);
|
GB_ASSERT(b->label->kind == Ast_Label);
|
||||||
if (b->label == label) {
|
if (b->label == label) {
|
||||||
b->break_ = break_;
|
b->break_ = break_;
|
||||||
b->continue_ = continue_;
|
b->continue_ = continue_;
|
||||||
@@ -3923,7 +3923,7 @@ void ir_pop_target_list(irProcedure *proc) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
irValue *ir_gen_anonymous_proc_lit(irModule *m, String prefix_name, AstNode *expr, irProcedure *proc = nullptr) {
|
irValue *ir_gen_anonymous_proc_lit(irModule *m, String prefix_name, Ast *expr, irProcedure *proc = nullptr) {
|
||||||
ast_node(pl, ProcLit, expr);
|
ast_node(pl, ProcLit, expr);
|
||||||
|
|
||||||
// NOTE(bill): Generate a new name
|
// NOTE(bill): Generate a new name
|
||||||
@@ -4095,7 +4095,7 @@ irValue *ir_find_global_variable(irProcedure *proc, String name) {
|
|||||||
return *value;
|
return *value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_build_stmt_list(irProcedure *proc, Array<AstNode *> stmts);
|
void ir_build_stmt_list(irProcedure *proc, Array<Ast *> stmts);
|
||||||
|
|
||||||
|
|
||||||
bool is_double_pointer(Type *t) {
|
bool is_double_pointer(Type *t) {
|
||||||
@@ -4121,14 +4121,14 @@ irValue *ir_emit_source_code_location(irProcedure *proc, String procedure, Token
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
irValue *ir_emit_source_code_location(irProcedure *proc, AstNode *node) {
|
irValue *ir_emit_source_code_location(irProcedure *proc, Ast *node) {
|
||||||
String proc_name = {};
|
String proc_name = {};
|
||||||
if (proc->entity) {
|
if (proc->entity) {
|
||||||
proc_name = proc->entity->token.string;
|
proc_name = proc->entity->token.string;
|
||||||
}
|
}
|
||||||
TokenPos pos = {};
|
TokenPos pos = {};
|
||||||
if (node) {
|
if (node) {
|
||||||
pos = ast_node_token(node).pos;
|
pos = ast_token(node).pos;
|
||||||
}
|
}
|
||||||
return ir_emit_source_code_location(proc, proc_name, pos);
|
return ir_emit_source_code_location(proc, proc_name, pos);
|
||||||
}
|
}
|
||||||
@@ -4140,7 +4140,7 @@ void ir_emit_increment(irProcedure *proc, irValue *addr) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_init_data_with_defaults(irProcedure *proc, irValue *ptr, irValue *count, AstNode *expr) {
|
void ir_init_data_with_defaults(irProcedure *proc, irValue *ptr, irValue *count, Ast *expr) {
|
||||||
Type *elem_type = type_deref(ir_type(ptr));
|
Type *elem_type = type_deref(ir_type(ptr));
|
||||||
GB_ASSERT(is_type_struct(elem_type) || is_type_array(elem_type));
|
GB_ASSERT(is_type_struct(elem_type) || is_type_array(elem_type));
|
||||||
|
|
||||||
@@ -4172,7 +4172,7 @@ void ir_init_data_with_defaults(irProcedure *proc, irValue *ptr, irValue *count,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv, BuiltinProcId id) {
|
irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, BuiltinProcId id) {
|
||||||
ast_node(ce, CallExpr, expr);
|
ast_node(ce, CallExpr, expr);
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
@@ -4181,10 +4181,10 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
String name = bd->name;
|
String name = bd->name;
|
||||||
GB_ASSERT(name == "location");
|
GB_ASSERT(name == "location");
|
||||||
String procedure = proc->entity->token.string;
|
String procedure = proc->entity->token.string;
|
||||||
TokenPos pos = ast_node_token(ce->proc).pos;
|
TokenPos pos = ast_token(ce->proc).pos;
|
||||||
if (ce->args.count > 0) {
|
if (ce->args.count > 0) {
|
||||||
AstNode *ident = unselector_expr(ce->args[0]);
|
Ast *ident = unselector_expr(ce->args[0]);
|
||||||
GB_ASSERT(ident->kind == AstNode_Ident);
|
GB_ASSERT(ident->kind == Ast_Ident);
|
||||||
Entity *e = entity_of_ident(ident);
|
Entity *e = entity_of_ident(ident);
|
||||||
GB_ASSERT(e != nullptr);
|
GB_ASSERT(e != nullptr);
|
||||||
|
|
||||||
@@ -4200,7 +4200,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
}
|
}
|
||||||
|
|
||||||
case BuiltinProc_type_info_of: {
|
case BuiltinProc_type_info_of: {
|
||||||
AstNode *arg = ce->args[0];
|
Ast *arg = ce->args[0];
|
||||||
TypeAndValue tav = type_and_value_of_expr(proc->module->info, arg);
|
TypeAndValue tav = type_and_value_of_expr(proc->module->info, arg);
|
||||||
if (tav.mode == Addressing_Type) {
|
if (tav.mode == Addressing_Type) {
|
||||||
Type *t = default_type(type_of_expr(proc->module->info, arg));
|
Type *t = default_type(type_of_expr(proc->module->info, arg));
|
||||||
@@ -4214,7 +4214,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
}
|
}
|
||||||
|
|
||||||
case BuiltinProc_typeid_of: {
|
case BuiltinProc_typeid_of: {
|
||||||
AstNode *arg = ce->args[0];
|
Ast *arg = ce->args[0];
|
||||||
TypeAndValue tav = type_and_value_of_expr(proc->module->info, arg);
|
TypeAndValue tav = type_and_value_of_expr(proc->module->info, arg);
|
||||||
if (tav.mode == Addressing_Type) {
|
if (tav.mode == Addressing_Type) {
|
||||||
Type *t = default_type(type_of_expr(proc->module->info, arg));
|
Type *t = default_type(type_of_expr(proc->module->info, arg));
|
||||||
@@ -4340,14 +4340,14 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
|
|
||||||
irValue *len = ir_emit_conv(proc, ir_build_expr(proc, ce->args[1]), t_int);
|
irValue *len = ir_emit_conv(proc, ir_build_expr(proc, ce->args[1]), t_int);
|
||||||
|
|
||||||
ir_emit_slice_bounds_check(proc, ast_node_token(ce->args[1]), v_zero, len, len, false);
|
ir_emit_slice_bounds_check(proc, ast_token(ce->args[1]), v_zero, len, len, false);
|
||||||
|
|
||||||
irValue *slice_size = len;
|
irValue *slice_size = len;
|
||||||
if (esz != 1) {
|
if (esz != 1) {
|
||||||
slice_size = ir_emit_arith(proc, Token_Mul, elem_size, len, t_int);
|
slice_size = ir_emit_arith(proc, Token_Mul, elem_size, len, t_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenPos pos = ast_node_token(ce->args[0]).pos;
|
TokenPos pos = ast_token(ce->args[0]).pos;
|
||||||
|
|
||||||
auto args = array_make<irValue *>(proc->module->allocator, 3);
|
auto args = array_make<irValue *>(proc->module->allocator, 3);
|
||||||
args[0] = slice_size;
|
args[0] = slice_size;
|
||||||
@@ -4390,7 +4390,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
cap = ir_emit_conv(proc, ir_build_expr(proc, ce->args[2]), t_int);
|
cap = ir_emit_conv(proc, ir_build_expr(proc, ce->args[2]), t_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
ir_emit_dynamic_array_bounds_check(proc, ast_node_token(ce->args[0]), v_zero, len, cap);
|
ir_emit_dynamic_array_bounds_check(proc, ast_token(ce->args[0]), v_zero, len, cap);
|
||||||
|
|
||||||
irValue *array = ir_add_local_generated(proc, type);
|
irValue *array = ir_add_local_generated(proc, type);
|
||||||
|
|
||||||
@@ -4413,7 +4413,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
|
|
||||||
gbAllocator a = proc->module->allocator;
|
gbAllocator a = proc->module->allocator;
|
||||||
|
|
||||||
AstNode *node = ce->args[0];
|
Ast *node = ce->args[0];
|
||||||
TypeAndValue tav = type_and_value_of_expr(proc->module->info, node);
|
TypeAndValue tav = type_and_value_of_expr(proc->module->info, node);
|
||||||
Type *type = base_type(tav.type);
|
Type *type = base_type(tav.type);
|
||||||
|
|
||||||
@@ -4561,7 +4561,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
}
|
}
|
||||||
Type *type = ir_type(array_ptr);
|
Type *type = ir_type(array_ptr);
|
||||||
{
|
{
|
||||||
TokenPos pos = ast_node_token(ce->args[0]).pos;
|
TokenPos pos = ast_token(ce->args[0]).pos;
|
||||||
GB_ASSERT_MSG(is_type_pointer(type), "%.*s(%td) %s",
|
GB_ASSERT_MSG(is_type_pointer(type), "%.*s(%td) %s",
|
||||||
LIT(pos.file), pos.line,
|
LIT(pos.file), pos.line,
|
||||||
type_to_string(type));
|
type_to_string(type));
|
||||||
@@ -4586,7 +4586,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
isize arg_index = 0;
|
isize arg_index = 0;
|
||||||
isize arg_count = 0;
|
isize arg_count = 0;
|
||||||
for_array(i, ce->args) {
|
for_array(i, ce->args) {
|
||||||
AstNode *a = ce->args[i];
|
Ast *a = ce->args[i];
|
||||||
Type *at = base_type(type_of_expr(proc->module->info, a));
|
Type *at = base_type(type_of_expr(proc->module->info, a));
|
||||||
if (at->kind == Type_Tuple) {
|
if (at->kind == Type_Tuple) {
|
||||||
arg_count += at->Tuple.variable_count;
|
arg_count += at->Tuple.variable_count;
|
||||||
@@ -4829,15 +4829,15 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr);
|
irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr);
|
||||||
|
|
||||||
irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
irValue *ir_build_expr(irProcedure *proc, Ast *expr) {
|
||||||
irValue *v = ir_build_expr_internal(proc, expr);
|
irValue *v = ir_build_expr_internal(proc, expr);
|
||||||
ir_add_debug_location_to_value(proc, v, expr);
|
ir_add_debug_location_to_value(proc, v, expr);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
|
irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
|
||||||
expr = unparen_expr(expr);
|
expr = unparen_expr(expr);
|
||||||
|
|
||||||
TypeAndValue tv = type_and_value_of_expr(proc->module->info, expr);
|
TypeAndValue tv = type_and_value_of_expr(proc->module->info, expr);
|
||||||
@@ -4900,7 +4900,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
|
|||||||
Entity *e = entity_of_ident(expr);
|
Entity *e = entity_of_ident(expr);
|
||||||
GB_ASSERT_MSG(e != nullptr, "%s", expr_to_string(expr));
|
GB_ASSERT_MSG(e != nullptr, "%s", expr_to_string(expr));
|
||||||
if (e->kind == Entity_Builtin) {
|
if (e->kind == Entity_Builtin) {
|
||||||
Token token = ast_node_token(expr);
|
Token token = ast_token(expr);
|
||||||
GB_PANIC("TODO(bill): ir_build_expr Entity_Builtin '%.*s'\n"
|
GB_PANIC("TODO(bill): ir_build_expr Entity_Builtin '%.*s'\n"
|
||||||
"\t at %.*s(%td:%td)", LIT(builtin_procs[e->Builtin.id].name),
|
"\t at %.*s(%td:%td)", LIT(builtin_procs[e->Builtin.id].name),
|
||||||
LIT(token.pos.file), token.pos.line, token.pos.column);
|
LIT(token.pos.file), token.pos.line, token.pos.column);
|
||||||
@@ -4974,7 +4974,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(ta, TypeAssertion, expr);
|
case_ast_node(ta, TypeAssertion, expr);
|
||||||
TokenPos pos = ast_node_token(expr).pos;
|
TokenPos pos = ast_token(expr).pos;
|
||||||
Type *type = tv.type;
|
Type *type = tv.type;
|
||||||
irValue *e = ir_build_expr(proc, ta->expr);
|
irValue *e = ir_build_expr(proc, ta->expr);
|
||||||
Type *t = type_deref(ir_type(e));
|
Type *t = type_deref(ir_type(e));
|
||||||
@@ -5007,15 +5007,15 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
|
|||||||
case_ast_node(ue, UnaryExpr, expr);
|
case_ast_node(ue, UnaryExpr, expr);
|
||||||
switch (ue->op.kind) {
|
switch (ue->op.kind) {
|
||||||
case Token_And: {
|
case Token_And: {
|
||||||
AstNode *ue_expr = unparen_expr(ue->expr);
|
Ast *ue_expr = unparen_expr(ue->expr);
|
||||||
if (ue_expr->kind == AstNode_TypeAssertion) {
|
if (ue_expr->kind == Ast_TypeAssertion) {
|
||||||
gbAllocator a = proc->module->allocator;
|
gbAllocator a = proc->module->allocator;
|
||||||
|
|
||||||
|
|
||||||
GB_ASSERT(is_type_pointer(tv.type));
|
GB_ASSERT(is_type_pointer(tv.type));
|
||||||
|
|
||||||
ast_node(ta, TypeAssertion, ue_expr);
|
ast_node(ta, TypeAssertion, ue_expr);
|
||||||
TokenPos pos = ast_node_token(expr).pos;
|
TokenPos pos = ast_token(expr).pos;
|
||||||
Type *type = type_of_expr(proc->module->info, ue_expr);
|
Type *type = type_of_expr(proc->module->info, ue_expr);
|
||||||
GB_ASSERT(!is_type_tuple(type));
|
GB_ASSERT(!is_type_tuple(type));
|
||||||
|
|
||||||
@@ -5147,7 +5147,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
|
|||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *p = unparen_expr(ce->proc);
|
Ast *p = unparen_expr(ce->proc);
|
||||||
if (proc_mode == Addressing_Builtin) {
|
if (proc_mode == Addressing_Builtin) {
|
||||||
Entity *e = entity_of_ident(p);
|
Entity *e = entity_of_ident(p);
|
||||||
BuiltinProcId id = BuiltinProc_Invalid;
|
BuiltinProcId id = BuiltinProc_Invalid;
|
||||||
@@ -5170,9 +5170,9 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
|
|||||||
auto args = array_make<irValue *>(proc->module->allocator, pt->param_count);
|
auto args = array_make<irValue *>(proc->module->allocator, pt->param_count);
|
||||||
|
|
||||||
for_array(arg_index, ce->args) {
|
for_array(arg_index, ce->args) {
|
||||||
AstNode *arg = ce->args[arg_index];
|
Ast *arg = ce->args[arg_index];
|
||||||
ast_node(fv, FieldValue, arg);
|
ast_node(fv, FieldValue, arg);
|
||||||
GB_ASSERT(fv->field->kind == AstNode_Ident);
|
GB_ASSERT(fv->field->kind == Ast_Ident);
|
||||||
String name = fv->field->Ident.token.string;
|
String name = fv->field->Ident.token.string;
|
||||||
isize index = lookup_procedure_parameter(pt, name);
|
isize index = lookup_procedure_parameter(pt, name);
|
||||||
GB_ASSERT(index >= 0);
|
GB_ASSERT(index >= 0);
|
||||||
@@ -5210,7 +5210,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
|
|||||||
|
|
||||||
isize arg_count = 0;
|
isize arg_count = 0;
|
||||||
for_array(i, ce->args) {
|
for_array(i, ce->args) {
|
||||||
AstNode *arg = ce->args[i];
|
Ast *arg = ce->args[i];
|
||||||
TypeAndValue tav = type_and_value_of_expr(proc->module->info, arg);
|
TypeAndValue tav = type_and_value_of_expr(proc->module->info, arg);
|
||||||
GB_ASSERT_MSG(tav.mode != Addressing_Invalid, "%s", expr_to_string(arg));
|
GB_ASSERT_MSG(tav.mode != Addressing_Invalid, "%s", expr_to_string(arg));
|
||||||
GB_ASSERT_MSG(tav.mode != Addressing_ProcGroup, "%s", expr_to_string(arg));
|
GB_ASSERT_MSG(tav.mode != Addressing_ProcGroup, "%s", expr_to_string(arg));
|
||||||
@@ -5238,7 +5238,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
|
|||||||
if (proc->entity != nullptr) {
|
if (proc->entity != nullptr) {
|
||||||
proc_name = proc->entity->token.string;
|
proc_name = proc->entity->token.string;
|
||||||
}
|
}
|
||||||
TokenPos pos = ast_node_token(ce->proc).pos;
|
TokenPos pos = ast_token(ce->proc).pos;
|
||||||
|
|
||||||
TypeTuple *param_tuple = nullptr;
|
TypeTuple *param_tuple = nullptr;
|
||||||
if (pt->params) {
|
if (pt->params) {
|
||||||
@@ -5247,7 +5247,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for_array(i, ce->args) {
|
for_array(i, ce->args) {
|
||||||
AstNode *arg = ce->args[i];
|
Ast *arg = ce->args[i];
|
||||||
TypeAndValue arg_tv = type_and_value_of_expr(proc->module->info, arg);
|
TypeAndValue arg_tv = type_and_value_of_expr(proc->module->info, arg);
|
||||||
if (arg_tv.mode == Addressing_Type) {
|
if (arg_tv.mode == Addressing_Type) {
|
||||||
args[arg_index++] = ir_value_nil(proc->module->allocator, arg_tv.type);
|
args[arg_index++] = ir_value_nil(proc->module->allocator, arg_tv.type);
|
||||||
@@ -5394,7 +5394,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
|
|||||||
case_end;
|
case_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
GB_PANIC("Unexpected expression: %.*s", LIT(ast_node_strings[expr->kind]));
|
GB_PANIC("Unexpected expression: %.*s", LIT(ast_strings[expr->kind]));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5417,11 +5417,11 @@ irValue *ir_get_using_variable(irProcedure *proc, Entity *e) {
|
|||||||
return ir_emit_deep_field_gep(proc, v, sel);
|
return ir_emit_deep_field_gep(proc, v, sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ir_is_elem_const(irModule *m, AstNode *elem, Type *elem_type) {
|
bool ir_is_elem_const(irModule *m, Ast *elem, Type *elem_type) {
|
||||||
if (!elem_type_can_be_constant(elem_type)) {
|
if (!elem_type_can_be_constant(elem_type)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (elem->kind == AstNode_FieldValue) {
|
if (elem->kind == Ast_FieldValue) {
|
||||||
elem = elem->FieldValue.value;
|
elem = elem->FieldValue.value;
|
||||||
}
|
}
|
||||||
TypeAndValue tav = type_and_value_of_expr(m->info, elem);
|
TypeAndValue tav = type_and_value_of_expr(m->info, elem);
|
||||||
@@ -5429,7 +5429,7 @@ bool ir_is_elem_const(irModule *m, AstNode *elem, Type *elem_type) {
|
|||||||
return tav.value.kind != ExactValue_Invalid;
|
return tav.value.kind != ExactValue_Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
irAddr ir_build_addr_from_entity(irProcedure *proc, Entity *e, AstNode *expr) {
|
irAddr ir_build_addr_from_entity(irProcedure *proc, Entity *e, Ast *expr) {
|
||||||
GB_ASSERT(e != nullptr);
|
GB_ASSERT(e != nullptr);
|
||||||
GB_ASSERT(e->kind != Entity_Constant);
|
GB_ASSERT(e->kind != Entity_Constant);
|
||||||
|
|
||||||
@@ -5452,7 +5452,7 @@ irAddr ir_build_addr_from_entity(irProcedure *proc, Entity *e, AstNode *expr) {
|
|||||||
return ir_addr(v);
|
return ir_addr(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
|
||||||
switch (expr->kind) {
|
switch (expr->kind) {
|
||||||
case_ast_node(i, Implicit, expr);
|
case_ast_node(i, Implicit, expr);
|
||||||
irValue *v = nullptr;
|
irValue *v = nullptr;
|
||||||
@@ -5483,8 +5483,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
|
|
||||||
case_ast_node(se, SelectorExpr, expr);
|
case_ast_node(se, SelectorExpr, expr);
|
||||||
ir_emit_comment(proc, str_lit("SelectorExpr"));
|
ir_emit_comment(proc, str_lit("SelectorExpr"));
|
||||||
AstNode *sel = unparen_expr(se->selector);
|
Ast *sel = unparen_expr(se->selector);
|
||||||
if (sel->kind == AstNode_Ident) {
|
if (sel->kind == Ast_Ident) {
|
||||||
String selector = sel->Ident.token.string;
|
String selector = sel->Ident.token.string;
|
||||||
TypeAndValue tav = type_and_value_of_expr(proc->module->info, se->expr);
|
TypeAndValue tav = type_and_value_of_expr(proc->module->info, se->expr);
|
||||||
|
|
||||||
@@ -5568,7 +5568,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
|
|
||||||
case_ast_node(ta, TypeAssertion, expr);
|
case_ast_node(ta, TypeAssertion, expr);
|
||||||
gbAllocator a = proc->module->allocator;
|
gbAllocator a = proc->module->allocator;
|
||||||
TokenPos pos = ast_node_token(expr).pos;
|
TokenPos pos = ast_token(expr).pos;
|
||||||
irValue *e = ir_build_expr(proc, ta->expr);
|
irValue *e = ir_build_expr(proc, ta->expr);
|
||||||
Type *t = type_deref(ir_type(e));
|
Type *t = type_deref(ir_type(e));
|
||||||
if (is_type_union(t)) {
|
if (is_type_union(t)) {
|
||||||
@@ -5644,7 +5644,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
auto index_tv = type_and_value_of_expr(proc->module->info, ie->index);
|
auto index_tv = type_and_value_of_expr(proc->module->info, ie->index);
|
||||||
if (index_tv.mode != Addressing_Constant) {
|
if (index_tv.mode != Addressing_Constant) {
|
||||||
irValue *len = ir_const_int(a, t->Array.count);
|
irValue *len = ir_const_int(a, t->Array.count);
|
||||||
ir_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
ir_emit_bounds_check(proc, ast_token(ie->index), index, len);
|
||||||
}
|
}
|
||||||
return ir_addr(elem);
|
return ir_addr(elem);
|
||||||
break;
|
break;
|
||||||
@@ -5663,7 +5663,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
irValue *elem = ir_slice_elem(proc, slice);
|
irValue *elem = ir_slice_elem(proc, slice);
|
||||||
irValue *index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int);
|
irValue *index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int);
|
||||||
irValue *len = ir_slice_len(proc, slice);
|
irValue *len = ir_slice_len(proc, slice);
|
||||||
ir_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
ir_emit_bounds_check(proc, ast_token(ie->index), index, len);
|
||||||
irValue *v = ir_emit_ptr_offset(proc, elem, index);
|
irValue *v = ir_emit_ptr_offset(proc, elem, index);
|
||||||
return ir_addr(v);
|
return ir_addr(v);
|
||||||
break;
|
break;
|
||||||
@@ -5682,7 +5682,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
irValue *elem = ir_dynamic_array_elem(proc, dynamic_array);
|
irValue *elem = ir_dynamic_array_elem(proc, dynamic_array);
|
||||||
irValue *len = ir_dynamic_array_len(proc, dynamic_array);
|
irValue *len = ir_dynamic_array_len(proc, dynamic_array);
|
||||||
irValue *index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int);
|
irValue *index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int);
|
||||||
ir_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
ir_emit_bounds_check(proc, ast_token(ie->index), index, len);
|
||||||
irValue *v = ir_emit_ptr_offset(proc, elem, index);
|
irValue *v = ir_emit_ptr_offset(proc, elem, index);
|
||||||
return ir_addr(v);
|
return ir_addr(v);
|
||||||
break;
|
break;
|
||||||
@@ -5707,7 +5707,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
len = ir_string_len(proc, str);
|
len = ir_string_len(proc, str);
|
||||||
|
|
||||||
index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int);
|
index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int);
|
||||||
ir_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
ir_emit_bounds_check(proc, ast_token(ie->index), index, len);
|
||||||
|
|
||||||
return ir_addr(ir_emit_ptr_offset(proc, elem, index));
|
return ir_addr(ir_emit_ptr_offset(proc, elem, index));
|
||||||
break;
|
break;
|
||||||
@@ -5845,7 +5845,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
if (proc->entity) {
|
if (proc->entity) {
|
||||||
proc_name = proc->entity->token.string;
|
proc_name = proc->entity->token.string;
|
||||||
}
|
}
|
||||||
TokenPos pos = ast_node_token(expr).pos;
|
TokenPos pos = ast_token(expr).pos;
|
||||||
|
|
||||||
switch (bt->kind) {
|
switch (bt->kind) {
|
||||||
default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break;
|
default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break;
|
||||||
@@ -5860,13 +5860,13 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
if (cl->elems.count > 0) {
|
if (cl->elems.count > 0) {
|
||||||
ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, exact_value_compound(expr)));
|
ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, exact_value_compound(expr)));
|
||||||
for_array(field_index, cl->elems) {
|
for_array(field_index, cl->elems) {
|
||||||
AstNode *elem = cl->elems[field_index];
|
Ast *elem = cl->elems[field_index];
|
||||||
|
|
||||||
irValue *field_expr = nullptr;
|
irValue *field_expr = nullptr;
|
||||||
Entity *field = nullptr;
|
Entity *field = nullptr;
|
||||||
isize index = field_index;
|
isize index = field_index;
|
||||||
|
|
||||||
if (elem->kind == AstNode_FieldValue) {
|
if (elem->kind == Ast_FieldValue) {
|
||||||
ast_node(fv, FieldValue, elem);
|
ast_node(fv, FieldValue, elem);
|
||||||
String name = fv->field->Ident.token.string;
|
String name = fv->field->Ident.token.string;
|
||||||
Selection sel = lookup_field(bt, name, false);
|
Selection sel = lookup_field(bt, name, false);
|
||||||
@@ -5909,7 +5909,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
ir_emit_runtime_call(proc, "__dynamic_map_reserve", args);
|
ir_emit_runtime_call(proc, "__dynamic_map_reserve", args);
|
||||||
}
|
}
|
||||||
for_array(field_index, cl->elems) {
|
for_array(field_index, cl->elems) {
|
||||||
AstNode *elem = cl->elems[field_index];
|
Ast *elem = cl->elems[field_index];
|
||||||
ast_node(fv, FieldValue, elem);
|
ast_node(fv, FieldValue, elem);
|
||||||
|
|
||||||
irValue *key = ir_build_expr(proc, fv->field);
|
irValue *key = ir_build_expr(proc, fv->field);
|
||||||
@@ -5941,7 +5941,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
irValue *items = ir_generate_array(proc->module, elem, item_count, str_lit("__dacl$"), cast(i64)cast(intptr)expr);
|
irValue *items = ir_generate_array(proc->module, elem, item_count, str_lit("__dacl$"), cast(i64)cast(intptr)expr);
|
||||||
|
|
||||||
for_array(field_index, cl->elems) {
|
for_array(field_index, cl->elems) {
|
||||||
AstNode *f = cl->elems[field_index];
|
Ast *f = cl->elems[field_index];
|
||||||
irValue *value = ir_emit_conv(proc, ir_build_expr(proc, f), elem);
|
irValue *value = ir_emit_conv(proc, ir_build_expr(proc, f), elem);
|
||||||
irValue *ep = ir_emit_array_epi(proc, items, cast(i32)field_index);
|
irValue *ep = ir_emit_array_epi(proc, items, cast(i32)field_index);
|
||||||
ir_emit_store(proc, ep, value);
|
ir_emit_store(proc, ep, value);
|
||||||
@@ -5964,7 +5964,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
if (cl->elems.count > 0) {
|
if (cl->elems.count > 0) {
|
||||||
ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, exact_value_compound(expr)));
|
ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, exact_value_compound(expr)));
|
||||||
for_array(i, cl->elems) {
|
for_array(i, cl->elems) {
|
||||||
AstNode *elem = cl->elems[i];
|
Ast *elem = cl->elems[i];
|
||||||
if (ir_is_elem_const(proc->module, elem, et)) {
|
if (ir_is_elem_const(proc->module, elem, et)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -5989,7 +5989,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
irValue *data = ir_emit_array_ep(proc, slice->ConstantSlice.backing_array, v_zero32);
|
irValue *data = ir_emit_array_ep(proc, slice->ConstantSlice.backing_array, v_zero32);
|
||||||
|
|
||||||
for_array(i, cl->elems) {
|
for_array(i, cl->elems) {
|
||||||
AstNode *elem = cl->elems[i];
|
Ast *elem = cl->elems[i];
|
||||||
if (ir_is_elem_const(proc->module, elem, et)) {
|
if (ir_is_elem_const(proc->module, elem, et)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -6022,12 +6022,12 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
for_array(field_index, cl->elems) {
|
for_array(field_index, cl->elems) {
|
||||||
AstNode *elem = cl->elems[field_index];
|
Ast *elem = cl->elems[field_index];
|
||||||
|
|
||||||
irValue *field_expr = nullptr;
|
irValue *field_expr = nullptr;
|
||||||
isize index = field_index;
|
isize index = field_index;
|
||||||
|
|
||||||
if (elem->kind == AstNode_FieldValue) {
|
if (elem->kind == Ast_FieldValue) {
|
||||||
ast_node(fv, FieldValue, elem);
|
ast_node(fv, FieldValue, elem);
|
||||||
Selection sel = lookup_field(bt, fv->field->Ident.token.string, false);
|
Selection sel = lookup_field(bt, fv->field->Ident.token.string, false);
|
||||||
index = sel.index[0];
|
index = sel.index[0];
|
||||||
@@ -6078,11 +6078,11 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
case_end;
|
case_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenPos token_pos = ast_node_token(expr).pos;
|
TokenPos token_pos = ast_token(expr).pos;
|
||||||
GB_PANIC("Unexpected address expression\n"
|
GB_PANIC("Unexpected address expression\n"
|
||||||
"\tAstNode: %.*s @ "
|
"\tAst: %.*s @ "
|
||||||
"%.*s(%td:%td)\n",
|
"%.*s(%td:%td)\n",
|
||||||
LIT(ast_node_strings[expr->kind]),
|
LIT(ast_strings[expr->kind]),
|
||||||
LIT(token_pos.file), token_pos.line, token_pos.column);
|
LIT(token_pos.file), token_pos.line, token_pos.column);
|
||||||
|
|
||||||
|
|
||||||
@@ -6103,7 +6103,7 @@ void ir_build_assign_op(irProcedure *proc, irAddr const &lhs, irValue *value, To
|
|||||||
ir_addr_store(proc, lhs, new_value);
|
ir_addr_store(proc, lhs, new_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_build_cond(irProcedure *proc, AstNode *cond, irBlock *true_block, irBlock *false_block) {
|
irValue *ir_build_cond(irProcedure *proc, Ast *cond, irBlock *true_block, irBlock *false_block) {
|
||||||
switch (cond->kind) {
|
switch (cond->kind) {
|
||||||
case_ast_node(pe, ParenExpr, cond);
|
case_ast_node(pe, ParenExpr, cond);
|
||||||
return ir_build_cond(proc, pe->expr, true_block, false_block);
|
return ir_build_cond(proc, pe->expr, true_block, false_block);
|
||||||
@@ -6136,7 +6136,7 @@ irValue *ir_build_cond(irProcedure *proc, AstNode *cond, irBlock *true_block, ir
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_build_nested_proc(irProcedure *proc, AstNodeProcLit *pd, Entity *e) {
|
void ir_build_nested_proc(irProcedure *proc, AstProcLit *pd, Entity *e) {
|
||||||
GB_ASSERT(pd->body != nullptr);
|
GB_ASSERT(pd->body != nullptr);
|
||||||
|
|
||||||
if (ir_min_dep_entity(proc->module, e) == false) {
|
if (ir_min_dep_entity(proc->module, e) == false) {
|
||||||
@@ -6173,14 +6173,14 @@ void ir_build_nested_proc(irProcedure *proc, AstNodeProcLit *pd, Entity *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ir_build_constant_value_decl(irProcedure *proc, AstNodeValueDecl *vd) {
|
void ir_build_constant_value_decl(irProcedure *proc, AstValueDecl *vd) {
|
||||||
if (vd == nullptr || vd->is_mutable) {
|
if (vd == nullptr || vd->is_mutable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for_array(i, vd->names) {
|
for_array(i, vd->names) {
|
||||||
AstNode *ident = vd->names[i];
|
Ast *ident = vd->names[i];
|
||||||
GB_ASSERT(ident->kind == AstNode_Ident);
|
GB_ASSERT(ident->kind == Ast_Ident);
|
||||||
Entity *e = entity_of_ident(ident);
|
Entity *e = entity_of_ident(ident);
|
||||||
GB_ASSERT(e != nullptr);
|
GB_ASSERT(e != nullptr);
|
||||||
switch (e->kind) {
|
switch (e->kind) {
|
||||||
@@ -6276,10 +6276,10 @@ void ir_build_constant_value_decl(irProcedure *proc, AstNodeValueDecl *vd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_build_stmt_list(irProcedure *proc, Array<AstNode *> stmts) {
|
void ir_build_stmt_list(irProcedure *proc, Array<Ast *> stmts) {
|
||||||
// NOTE(bill): Precollect constant entities
|
// NOTE(bill): Precollect constant entities
|
||||||
for_array(i, stmts) {
|
for_array(i, stmts) {
|
||||||
AstNode *stmt = stmts[i];
|
Ast *stmt = stmts[i];
|
||||||
switch (stmt->kind) {
|
switch (stmt->kind) {
|
||||||
case_ast_node(vd, ValueDecl, stmt);
|
case_ast_node(vd, ValueDecl, stmt);
|
||||||
ir_build_constant_value_decl(proc, vd);
|
ir_build_constant_value_decl(proc, vd);
|
||||||
@@ -6295,8 +6295,8 @@ void ir_build_stmt_list(irProcedure *proc, Array<AstNode *> stmts) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_build_stmt_internal(irProcedure *proc, AstNode *node);
|
void ir_build_stmt_internal(irProcedure *proc, Ast *node);
|
||||||
void ir_build_stmt(irProcedure *proc, AstNode *node) {
|
void ir_build_stmt(irProcedure *proc, Ast *node) {
|
||||||
u64 prev_stmt_state_flags = proc->module->stmt_state_flags;
|
u64 prev_stmt_state_flags = proc->module->stmt_state_flags;
|
||||||
|
|
||||||
if (node->stmt_state_flags != 0) {
|
if (node->stmt_state_flags != 0) {
|
||||||
@@ -6319,7 +6319,7 @@ void ir_build_stmt(irProcedure *proc, AstNode *node) {
|
|||||||
proc->module->stmt_state_flags = prev_stmt_state_flags;
|
proc->module->stmt_state_flags = prev_stmt_state_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_build_when_stmt(irProcedure *proc, AstNodeWhenStmt *ws) {
|
void ir_build_when_stmt(irProcedure *proc, AstWhenStmt *ws) {
|
||||||
irValue *cond = ir_build_expr(proc, ws->cond);
|
irValue *cond = ir_build_expr(proc, ws->cond);
|
||||||
GB_ASSERT(cond->kind == irValue_Constant &&
|
GB_ASSERT(cond->kind == irValue_Constant &&
|
||||||
is_type_boolean(ir_type(cond)));
|
is_type_boolean(ir_type(cond)));
|
||||||
@@ -6329,10 +6329,10 @@ void ir_build_when_stmt(irProcedure *proc, AstNodeWhenStmt *ws) {
|
|||||||
ir_build_stmt_list(proc, ws->body->BlockStmt.stmts);
|
ir_build_stmt_list(proc, ws->body->BlockStmt.stmts);
|
||||||
} else if (ws->else_stmt) {
|
} else if (ws->else_stmt) {
|
||||||
switch (ws->else_stmt->kind) {
|
switch (ws->else_stmt->kind) {
|
||||||
case AstNode_BlockStmt:
|
case Ast_BlockStmt:
|
||||||
ir_build_stmt_list(proc, ws->else_stmt->BlockStmt.stmts);
|
ir_build_stmt_list(proc, ws->else_stmt->BlockStmt.stmts);
|
||||||
break;
|
break;
|
||||||
case AstNode_WhenStmt:
|
case Ast_WhenStmt:
|
||||||
ir_build_when_stmt(proc, &ws->else_stmt->WhenStmt);
|
ir_build_when_stmt(proc, &ws->else_stmt->WhenStmt);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -6498,7 +6498,7 @@ void ir_build_range_string(irProcedure *proc, irValue *expr, Type *val_type,
|
|||||||
if (done_) *done_ = done;
|
if (done_) *done_ = done;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_build_range_interval(irProcedure *proc, AstNodeBinaryExpr *node, Type *val_type,
|
void ir_build_range_interval(irProcedure *proc, AstBinaryExpr *node, Type *val_type,
|
||||||
irValue **val_, irValue **idx_, irBlock **loop_, irBlock **done_) {
|
irValue **val_, irValue **idx_, irBlock **loop_, irBlock **done_) {
|
||||||
// TODO(bill): How should the behaviour work for lower and upper bounds checking for iteration?
|
// TODO(bill): How should the behaviour work for lower and upper bounds checking for iteration?
|
||||||
// If 'lower' is changed, should 'val' do so or is that not typical behaviour?
|
// If 'lower' is changed, should 'val' do so or is that not typical behaviour?
|
||||||
@@ -6556,14 +6556,14 @@ void ir_build_range_interval(irProcedure *proc, AstNodeBinaryExpr *node, Type *v
|
|||||||
if (done_) *done_ = done;
|
if (done_) *done_ = done;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_store_type_case_implicit(irProcedure *proc, AstNode *clause, irValue *value) {
|
void ir_store_type_case_implicit(irProcedure *proc, Ast *clause, irValue *value) {
|
||||||
Entity *e = implicit_entity_of_node(proc->module->info, clause);
|
Entity *e = implicit_entity_of_node(proc->module->info, clause);
|
||||||
GB_ASSERT(e != nullptr);
|
GB_ASSERT(e != nullptr);
|
||||||
irValue *x = ir_add_local(proc, e, nullptr, false);
|
irValue *x = ir_add_local(proc, e, nullptr, false);
|
||||||
ir_emit_store(proc, x, value);
|
ir_emit_store(proc, x, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_type_case_body(irProcedure *proc, AstNode *label, AstNode *clause, irBlock *body, irBlock *done) {
|
void ir_type_case_body(irProcedure *proc, Ast *label, Ast *clause, irBlock *body, irBlock *done) {
|
||||||
ast_node(cc, CaseClause, clause);
|
ast_node(cc, CaseClause, clause);
|
||||||
|
|
||||||
ir_push_target_list(proc, label, done, nullptr, nullptr);
|
ir_push_target_list(proc, label, done, nullptr, nullptr);
|
||||||
@@ -6575,7 +6575,7 @@ void ir_type_case_body(irProcedure *proc, AstNode *label, AstNode *clause, irBlo
|
|||||||
ir_emit_jump(proc, done);
|
ir_emit_jump(proc, done);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
|
||||||
switch (node->kind) {
|
switch (node->kind) {
|
||||||
case_ast_node(bs, EmptyStmt, node);
|
case_ast_node(bs, EmptyStmt, node);
|
||||||
case_end;
|
case_end;
|
||||||
@@ -6586,8 +6586,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
|
|
||||||
case_ast_node(us, UsingStmt, node);
|
case_ast_node(us, UsingStmt, node);
|
||||||
for_array(i, us->list) {
|
for_array(i, us->list) {
|
||||||
AstNode *decl = unparen_expr(us->list[i]);
|
Ast *decl = unparen_expr(us->list[i]);
|
||||||
// if (decl->kind == AstNode_GenDecl) {
|
// if (decl->kind == Ast_GenDecl) {
|
||||||
// ir_build_stmt(proc, decl);
|
// ir_build_stmt(proc, decl);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
@@ -6616,7 +6616,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
|
|
||||||
if (vd->values.count == 0) { // declared and zero-initialized
|
if (vd->values.count == 0) { // declared and zero-initialized
|
||||||
for_array(i, vd->names) {
|
for_array(i, vd->names) {
|
||||||
AstNode *name = vd->names[i];
|
Ast *name = vd->names[i];
|
||||||
if (!is_blank_ident(name)) {
|
if (!is_blank_ident(name)) {
|
||||||
ir_add_local_for_identifier(proc, name, true);
|
ir_add_local_for_identifier(proc, name, true);
|
||||||
}
|
}
|
||||||
@@ -6626,7 +6626,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
auto inits = array_make<irValue *>(m->tmp_allocator, 0, vd->names.count);
|
auto inits = array_make<irValue *>(m->tmp_allocator, 0, vd->names.count);
|
||||||
|
|
||||||
for_array(i, vd->names) {
|
for_array(i, vd->names) {
|
||||||
AstNode *name = vd->names[i];
|
Ast *name = vd->names[i];
|
||||||
irAddr lval = ir_addr(nullptr);
|
irAddr lval = ir_addr(nullptr);
|
||||||
if (!is_blank_ident(name)) {
|
if (!is_blank_ident(name)) {
|
||||||
ir_add_local_for_identifier(proc, name, false);
|
ir_add_local_for_identifier(proc, name, false);
|
||||||
@@ -6668,7 +6668,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
auto lvals = array_make<irAddr>(m->tmp_allocator);
|
auto lvals = array_make<irAddr>(m->tmp_allocator);
|
||||||
|
|
||||||
for_array(i, as->lhs) {
|
for_array(i, as->lhs) {
|
||||||
AstNode *lhs = as->lhs[i];
|
Ast *lhs = as->lhs[i];
|
||||||
irAddr lval = {};
|
irAddr lval = {};
|
||||||
if (!is_blank_ident(lhs)) {
|
if (!is_blank_ident(lhs)) {
|
||||||
lval = ir_build_addr(proc, lhs);
|
lval = ir_build_addr(proc, lhs);
|
||||||
@@ -6678,7 +6678,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
|
|
||||||
if (as->lhs.count == as->rhs.count) {
|
if (as->lhs.count == as->rhs.count) {
|
||||||
if (as->lhs.count == 1) {
|
if (as->lhs.count == 1) {
|
||||||
AstNode *rhs = as->rhs[0];
|
Ast *rhs = as->rhs[0];
|
||||||
irValue *init = ir_build_expr(proc, rhs);
|
irValue *init = ir_build_expr(proc, rhs);
|
||||||
ir_addr_store(proc, lvals[0], init);
|
ir_addr_store(proc, lvals[0], init);
|
||||||
} else {
|
} else {
|
||||||
@@ -6749,7 +6749,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
ir_emit_comment(proc, str_lit("DeferStmt"));
|
ir_emit_comment(proc, str_lit("DeferStmt"));
|
||||||
isize scope_index = proc->scope_index;
|
isize scope_index = proc->scope_index;
|
||||||
// TODO(bill): What was the original rationale behind this line?
|
// TODO(bill): What was the original rationale behind this line?
|
||||||
// if (ds->stmt->kind == AstNode_BlockStmt) scope_index--;
|
// if (ds->stmt->kind == Ast_BlockStmt) scope_index--;
|
||||||
ir_add_defer_node(proc, scope_index, ds->stmt);
|
ir_add_defer_node(proc, scope_index, ds->stmt);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
@@ -6929,15 +6929,15 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
irValue *key = nullptr;
|
irValue *key = nullptr;
|
||||||
irBlock *loop = nullptr;
|
irBlock *loop = nullptr;
|
||||||
irBlock *done = nullptr;
|
irBlock *done = nullptr;
|
||||||
AstNode *expr = unparen_expr(rs->expr);
|
Ast *expr = unparen_expr(rs->expr);
|
||||||
bool is_map = false;
|
bool is_map = false;
|
||||||
|
|
||||||
TypeAndValue tav = type_and_value_of_expr(proc->module->info, expr);
|
TypeAndValue tav = type_and_value_of_expr(proc->module->info, expr);
|
||||||
|
|
||||||
if (is_ast_node_a_range(expr)) {
|
if (is_ast_range(expr)) {
|
||||||
ir_build_range_interval(proc, &expr->BinaryExpr, val0_type, &val, &key, &loop, &done);
|
ir_build_range_interval(proc, &expr->BinaryExpr, val0_type, &val, &key, &loop, &done);
|
||||||
} else if (tav.mode == Addressing_Type) {
|
} else if (tav.mode == Addressing_Type) {
|
||||||
TokenPos pos = ast_node_token(expr).pos;
|
TokenPos pos = ast_token(expr).pos;
|
||||||
gbAllocator a = proc->module->allocator;
|
gbAllocator a = proc->module->allocator;
|
||||||
Type *t = tav.type;
|
Type *t = tav.type;
|
||||||
GB_ASSERT(is_type_enum(t));
|
GB_ASSERT(is_type_enum(t));
|
||||||
@@ -7091,7 +7091,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
|
|
||||||
ast_node(body, BlockStmt, ss->body);
|
ast_node(body, BlockStmt, ss->body);
|
||||||
|
|
||||||
Array<AstNode *> default_stmts = {};
|
Array<Ast *> default_stmts = {};
|
||||||
irBlock *default_fall = nullptr;
|
irBlock *default_fall = nullptr;
|
||||||
irBlock *default_block = nullptr;
|
irBlock *default_block = nullptr;
|
||||||
|
|
||||||
@@ -7100,7 +7100,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
|
|
||||||
isize case_count = body->stmts.count;
|
isize case_count = body->stmts.count;
|
||||||
for_array(i, body->stmts) {
|
for_array(i, body->stmts) {
|
||||||
AstNode *clause = body->stmts[i];
|
Ast *clause = body->stmts[i];
|
||||||
irBlock *body = fall;
|
irBlock *body = fall;
|
||||||
|
|
||||||
ast_node(cc, CaseClause, clause);
|
ast_node(cc, CaseClause, clause);
|
||||||
@@ -7132,10 +7132,10 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
|
|
||||||
irBlock *next_cond = nullptr;
|
irBlock *next_cond = nullptr;
|
||||||
for_array(j, cc->list) {
|
for_array(j, cc->list) {
|
||||||
AstNode *expr = unparen_expr(cc->list[j]);
|
Ast *expr = unparen_expr(cc->list[j]);
|
||||||
next_cond = ir_new_block(proc, clause, "switch.case.next");
|
next_cond = ir_new_block(proc, clause, "switch.case.next");
|
||||||
irValue *cond = v_false;
|
irValue *cond = v_false;
|
||||||
if (is_ast_node_a_range(expr)) {
|
if (is_ast_range(expr)) {
|
||||||
ast_node(ie, BinaryExpr, expr);
|
ast_node(ie, BinaryExpr, expr);
|
||||||
TokenKind op = Token_Invalid;
|
TokenKind op = Token_Invalid;
|
||||||
switch (ie->op.kind) {
|
switch (ie->op.kind) {
|
||||||
@@ -7220,14 +7220,14 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
|
|
||||||
// NOTE(bill): Append this later
|
// NOTE(bill): Append this later
|
||||||
irBlock *done = ir_new_block(proc, node, "typeswitch.done");
|
irBlock *done = ir_new_block(proc, node, "typeswitch.done");
|
||||||
AstNode *default_ = nullptr;
|
Ast *default_ = nullptr;
|
||||||
|
|
||||||
ast_node(body, BlockStmt, ss->body);
|
ast_node(body, BlockStmt, ss->body);
|
||||||
|
|
||||||
gb_local_persist i32 weird_count = 0;
|
gb_local_persist i32 weird_count = 0;
|
||||||
|
|
||||||
for_array(i, body->stmts) {
|
for_array(i, body->stmts) {
|
||||||
AstNode *clause = body->stmts[i];
|
Ast *clause = body->stmts[i];
|
||||||
ast_node(cc, CaseClause, clause);
|
ast_node(cc, CaseClause, clause);
|
||||||
if (cc->list.count == 0) {
|
if (cc->list.count == 0) {
|
||||||
default_ = clause;
|
default_ = clause;
|
||||||
@@ -7439,13 +7439,13 @@ void ir_begin_procedure_body(irProcedure *proc) {
|
|||||||
for_array(i, params->variables) {
|
for_array(i, params->variables) {
|
||||||
ast_node(fl, FieldList, pt->params);
|
ast_node(fl, FieldList, pt->params);
|
||||||
GB_ASSERT(fl->list.count > 0);
|
GB_ASSERT(fl->list.count > 0);
|
||||||
GB_ASSERT(fl->list[0]->kind == AstNode_Field);
|
GB_ASSERT(fl->list[0]->kind == Ast_Field);
|
||||||
if (q_index == fl->list[param_index]->Field.names.count) {
|
if (q_index == fl->list[param_index]->Field.names.count) {
|
||||||
q_index = 0;
|
q_index = 0;
|
||||||
param_index++;
|
param_index++;
|
||||||
}
|
}
|
||||||
ast_node(field, Field, fl->list[param_index]);
|
ast_node(field, Field, fl->list[param_index]);
|
||||||
AstNode *name = field->names[q_index++];
|
Ast *name = field->names[q_index++];
|
||||||
|
|
||||||
Entity *e = params->variables[i];
|
Entity *e = params->variables[i];
|
||||||
if (e->kind != Entity_Variable) {
|
if (e->kind != Entity_Variable) {
|
||||||
@@ -7593,9 +7593,9 @@ void ir_build_proc(irValue *value, irProcedure *parent) {
|
|||||||
Entity *f = p->params->Tuple.variables[i];
|
Entity *f = p->params->Tuple.variables[i];
|
||||||
if (f->kind == Entity_Variable) {
|
if (f->kind == Entity_Variable) {
|
||||||
if (f->Variable.default_value.kind == ExactValue_Procedure) {
|
if (f->Variable.default_value.kind == ExactValue_Procedure) {
|
||||||
AstNode *expr = f->Variable.default_value.value_procedure;
|
Ast *expr = f->Variable.default_value.value_procedure;
|
||||||
GB_ASSERT(expr != nullptr);
|
GB_ASSERT(expr != nullptr);
|
||||||
if (expr->kind == AstNode_ProcLit) {
|
if (expr->kind == Ast_ProcLit) {
|
||||||
ir_gen_anonymous_proc_lit(proc->module, proc->name, expr, proc);
|
ir_gen_anonymous_proc_lit(proc->module, proc->name, expr, proc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8461,7 +8461,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
case Entity_Procedure: {
|
case Entity_Procedure: {
|
||||||
ast_node(pl, ProcLit, decl->proc_lit);
|
ast_node(pl, ProcLit, decl->proc_lit);
|
||||||
String original_name = name;
|
String original_name = name;
|
||||||
AstNode *body = pl->body;
|
Ast *body = pl->body;
|
||||||
|
|
||||||
if (e->Procedure.is_foreign) {
|
if (e->Procedure.is_foreign) {
|
||||||
name = e->token.string; // NOTE(bill): Don't use the mangled name
|
name = e->token.string; // NOTE(bill): Don't use the mangled name
|
||||||
@@ -8471,7 +8471,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
name = e->Procedure.link_name;
|
name = e->Procedure.link_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *type_expr = pl->type;
|
Ast *type_expr = pl->type;
|
||||||
|
|
||||||
irValue *p = ir_value_procedure(a, m, e, e->type, type_expr, body, name);
|
irValue *p = ir_value_procedure(a, m, e, e->type, type_expr, body, name);
|
||||||
p->Proc.tags = pl->tags;
|
p->Proc.tags = pl->tags;
|
||||||
@@ -8551,7 +8551,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
}
|
}
|
||||||
proc_type->Proc.abi_compat_result_type = proc_results->Tuple.variables[0]->type;
|
proc_type->Proc.abi_compat_result_type = proc_results->Tuple.variables[0]->type;
|
||||||
|
|
||||||
AstNode *body = alloc_ast_node(nullptr, AstNode_Invalid);
|
Ast *body = alloc_ast_node(nullptr, Ast_Invalid);
|
||||||
Entity *e = alloc_entity_procedure(nullptr, make_token_ident(name), proc_type, 0);
|
Entity *e = alloc_entity_procedure(nullptr, make_token_ident(name), proc_type, 0);
|
||||||
irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name);
|
irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name);
|
||||||
|
|
||||||
@@ -8629,7 +8629,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
}
|
}
|
||||||
proc_type->Proc.abi_compat_result_type = proc_results->Tuple.variables[0]->type;
|
proc_type->Proc.abi_compat_result_type = proc_results->Tuple.variables[0]->type;
|
||||||
|
|
||||||
AstNode *body = alloc_ast_node(nullptr, AstNode_Invalid);
|
Ast *body = alloc_ast_node(nullptr, Ast_Invalid);
|
||||||
Entity *e = alloc_entity_procedure(nullptr, make_token_ident(name), proc_type, 0);
|
Entity *e = alloc_entity_procedure(nullptr, make_token_ident(name), proc_type, 0);
|
||||||
irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name);
|
irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name);
|
||||||
|
|
||||||
@@ -8693,7 +8693,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
proc_params, 4,
|
proc_params, 4,
|
||||||
proc_results, 1, false, ProcCC_Std);
|
proc_results, 1, false, ProcCC_Std);
|
||||||
|
|
||||||
AstNode *body = alloc_ast_node(nullptr, AstNode_Invalid);
|
Ast *body = alloc_ast_node(nullptr, Ast_Invalid);
|
||||||
Entity *e = alloc_entity_procedure(a, nullptr, make_token_ident(name), proc_type, 0);
|
Entity *e = alloc_entity_procedure(a, nullptr, make_token_ident(name), proc_type, 0);
|
||||||
irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name);
|
irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name);
|
||||||
|
|
||||||
@@ -8719,7 +8719,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
nullptr, 0,
|
nullptr, 0,
|
||||||
nullptr, 0, false,
|
nullptr, 0, false,
|
||||||
ProcCC_Contextless);
|
ProcCC_Contextless);
|
||||||
AstNode *body = alloc_ast_node(nullptr, AstNode_Invalid);
|
Ast *body = alloc_ast_node(nullptr, Ast_Invalid);
|
||||||
Entity *e = alloc_entity_procedure(nullptr, make_token_ident(name), proc_type, 0);
|
Entity *e = alloc_entity_procedure(nullptr, make_token_ident(name), proc_type, 0);
|
||||||
irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name);
|
irValue *p = ir_value_procedure(a, m, e, proc_type, nullptr, body, name);
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -709,7 +709,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
|
|||||||
bool *visited = gb_alloc_array(m->tmp_allocator, bool, value_count);
|
bool *visited = gb_alloc_array(m->tmp_allocator, bool, value_count);
|
||||||
|
|
||||||
if (cl->elems.count > 0) {
|
if (cl->elems.count > 0) {
|
||||||
if (cl->elems[0]->kind == AstNode_FieldValue) {
|
if (cl->elems[0]->kind == Ast_FieldValue) {
|
||||||
isize elem_count = cl->elems.count;
|
isize elem_count = cl->elems.count;
|
||||||
for (isize i = 0; i < elem_count; i++) {
|
for (isize i = 0; i < elem_count; i++) {
|
||||||
ast_node(fv, FieldValue, cl->elems[i]);
|
ast_node(fv, FieldValue, cl->elems[i]);
|
||||||
@@ -765,13 +765,13 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
|
|||||||
}
|
}
|
||||||
case ExactValue_Procedure: {
|
case ExactValue_Procedure: {
|
||||||
irValue **found = nullptr;
|
irValue **found = nullptr;
|
||||||
AstNode *expr = value.value_procedure;
|
Ast *expr = value.value_procedure;
|
||||||
GB_ASSERT(expr != nullptr);
|
GB_ASSERT(expr != nullptr);
|
||||||
|
|
||||||
if (expr->kind == AstNode_ProcLit) {
|
if (expr->kind == Ast_ProcLit) {
|
||||||
found = map_get(&m->anonymous_proc_lits, hash_pointer(expr));
|
found = map_get(&m->anonymous_proc_lits, hash_pointer(expr));
|
||||||
} else {
|
} else {
|
||||||
GB_ASSERT(expr->kind == AstNode_Ident);
|
GB_ASSERT(expr->kind == Ast_Ident);
|
||||||
Entity *e = entity_of_ident(expr);
|
Entity *e = entity_of_ident(expr);
|
||||||
GB_ASSERT(e != nullptr);
|
GB_ASSERT(e != nullptr);
|
||||||
found = map_get(&m->values, hash_entity(e));
|
found = map_get(&m->values, hash_entity(e));
|
||||||
|
|||||||
+629
-629
File diff suppressed because it is too large
Load Diff
+251
-251
@@ -1,4 +1,4 @@
|
|||||||
struct AstNode;
|
struct Ast;
|
||||||
struct Scope;
|
struct Scope;
|
||||||
struct Type;
|
struct Type;
|
||||||
struct Entity;
|
struct Entity;
|
||||||
@@ -52,7 +52,7 @@ struct AstFile {
|
|||||||
AstPackage * pkg;
|
AstPackage * pkg;
|
||||||
Scope * scope;
|
Scope * scope;
|
||||||
|
|
||||||
AstNode * pkg_decl;
|
Ast * pkg_decl;
|
||||||
String fullpath;
|
String fullpath;
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
Array<Token> tokens;
|
Array<Token> tokens;
|
||||||
@@ -71,12 +71,12 @@ struct AstFile {
|
|||||||
bool allow_type;
|
bool allow_type;
|
||||||
isize when_level;
|
isize when_level;
|
||||||
|
|
||||||
Array<AstNode *> decls;
|
Array<Ast *> decls;
|
||||||
Array<AstNode *> imports; // 'import' 'using import'
|
Array<Ast *> imports; // 'import' 'using import'
|
||||||
isize directive_count;
|
isize directive_count;
|
||||||
|
|
||||||
|
|
||||||
AstNode * curr_proc;
|
Ast * curr_proc;
|
||||||
// DeclInfo * decl_info; // NOTE(bill): Created in checker
|
// DeclInfo * decl_info; // NOTE(bill): Created in checker
|
||||||
isize error_count;
|
isize error_count;
|
||||||
|
|
||||||
@@ -173,192 +173,192 @@ enum StmtAllowFlag {
|
|||||||
StmtAllowFlag_Context = 1<<2,
|
StmtAllowFlag_Context = 1<<2,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define AST_NODE_KINDS \
|
#define AST_KINDS \
|
||||||
AST_NODE_KIND(Ident, "identifier", struct { \
|
AST_KIND(Ident, "identifier", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Entity *entity; \
|
Entity *entity; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(Implicit, "implicit", Token) \
|
AST_KIND(Implicit, "implicit", Token) \
|
||||||
AST_NODE_KIND(Undef, "undef", Token) \
|
AST_KIND(Undef, "undef", Token) \
|
||||||
AST_NODE_KIND(BasicLit, "basic literal", struct { \
|
AST_KIND(BasicLit, "basic literal", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(BasicDirective, "basic directive", struct { \
|
AST_KIND(BasicDirective, "basic directive", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
String name; \
|
String name; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(Ellipsis, "ellipsis", struct { \
|
AST_KIND(Ellipsis, "ellipsis", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *expr; \
|
Ast *expr; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(ProcGroup, "procedure group", struct { \
|
AST_KIND(ProcGroup, "procedure group", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Token open; \
|
Token open; \
|
||||||
Token close; \
|
Token close; \
|
||||||
Array<AstNode *> args; \
|
Array<Ast *> args; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(ProcLit, "procedure literal", struct { \
|
AST_KIND(ProcLit, "procedure literal", struct { \
|
||||||
AstNode * type; \
|
Ast *type; \
|
||||||
AstNode * body; \
|
Ast *body; \
|
||||||
u64 tags; \
|
u64 tags; \
|
||||||
ProcInlining inlining; \
|
ProcInlining inlining; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(CompoundLit, "compound literal", struct { \
|
AST_KIND(CompoundLit, "compound literal", struct { \
|
||||||
AstNode *type; \
|
Ast *type; \
|
||||||
Array<AstNode *> elems; \
|
Array<Ast *> elems; \
|
||||||
Token open, close; \
|
Token open, close; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(_ExprBegin, "", struct {}) \
|
AST_KIND(_ExprBegin, "", struct {}) \
|
||||||
AST_NODE_KIND(BadExpr, "bad expression", struct { Token begin, end; }) \
|
AST_KIND(BadExpr, "bad expression", struct { Token begin, end; }) \
|
||||||
AST_NODE_KIND(TagExpr, "tag expression", struct { Token token, name; AstNode *expr; }) \
|
AST_KIND(TagExpr, "tag expression", struct { Token token, name; Ast *expr; }) \
|
||||||
AST_NODE_KIND(RunExpr, "run expression", struct { Token token, name; AstNode *expr; }) \
|
AST_KIND(RunExpr, "run expression", struct { Token token, name; Ast *expr; }) \
|
||||||
AST_NODE_KIND(UnaryExpr, "unary expression", struct { Token op; AstNode *expr; }) \
|
AST_KIND(UnaryExpr, "unary expression", struct { Token op; Ast *expr; }) \
|
||||||
AST_NODE_KIND(BinaryExpr, "binary expression", struct { Token op; AstNode *left, *right; } ) \
|
AST_KIND(BinaryExpr, "binary expression", struct { Token op; Ast *left, *right; } ) \
|
||||||
AST_NODE_KIND(ParenExpr, "parentheses expression", struct { AstNode *expr; Token open, close; }) \
|
AST_KIND(ParenExpr, "parentheses expression", struct { Ast *expr; Token open, close; }) \
|
||||||
AST_NODE_KIND(SelectorExpr, "selector expression", struct { Token token; AstNode *expr, *selector; }) \
|
AST_KIND(SelectorExpr, "selector expression", struct { Token token; Ast *expr, *selector; }) \
|
||||||
AST_NODE_KIND(IndexExpr, "index expression", struct { AstNode *expr, *index; Token open, close; }) \
|
AST_KIND(IndexExpr, "index expression", struct { Ast *expr, *index; Token open, close; }) \
|
||||||
AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \
|
AST_KIND(DerefExpr, "dereference expression", struct { Token op; Ast *expr; }) \
|
||||||
AST_NODE_KIND(SliceExpr, "slice expression", struct { \
|
AST_KIND(SliceExpr, "slice expression", struct { \
|
||||||
AstNode *expr; \
|
Ast *expr; \
|
||||||
Token open, close; \
|
Token open, close; \
|
||||||
Token interval; \
|
Token interval; \
|
||||||
AstNode *low, *high; \
|
Ast *low, *high; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(CallExpr, "call expression", struct { \
|
AST_KIND(CallExpr, "call expression", struct { \
|
||||||
AstNode * proc; \
|
Ast * proc; \
|
||||||
Array<AstNode *> args; \
|
Array<Ast *> args; \
|
||||||
Token open; \
|
Token open; \
|
||||||
Token close; \
|
Token close; \
|
||||||
Token ellipsis; \
|
Token ellipsis; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(FieldValue, "field value", struct { Token eq; AstNode *field, *value; }) \
|
AST_KIND(FieldValue, "field value", struct { Token eq; Ast *field, *value; }) \
|
||||||
AST_NODE_KIND(TernaryExpr, "ternary expression", struct { AstNode *cond, *x, *y; }) \
|
AST_KIND(TernaryExpr, "ternary expression", struct { Ast *cond, *x, *y; }) \
|
||||||
AST_NODE_KIND(TypeAssertion, "type assertion", struct { AstNode *expr; Token dot; AstNode *type; }) \
|
AST_KIND(TypeAssertion, "type assertion", struct { Ast *expr; Token dot; Ast *type; }) \
|
||||||
AST_NODE_KIND(TypeCast, "type cast", struct { Token token; AstNode *type, *expr; }) \
|
AST_KIND(TypeCast, "type cast", struct { Token token; Ast *type, *expr; }) \
|
||||||
AST_NODE_KIND(AutoCast, "auto_cast", struct { Token token; AstNode *expr; }) \
|
AST_KIND(AutoCast, "auto_cast", struct { Token token; Ast *expr; }) \
|
||||||
AST_NODE_KIND(_ExprEnd, "", struct {}) \
|
AST_KIND(_ExprEnd, "", struct {}) \
|
||||||
AST_NODE_KIND(_StmtBegin, "", struct {}) \
|
AST_KIND(_StmtBegin, "", struct {}) \
|
||||||
AST_NODE_KIND(BadStmt, "bad statement", struct { Token begin, end; }) \
|
AST_KIND(BadStmt, "bad statement", struct { Token begin, end; }) \
|
||||||
AST_NODE_KIND(EmptyStmt, "empty statement", struct { Token token; }) \
|
AST_KIND(EmptyStmt, "empty statement", struct { Token token; }) \
|
||||||
AST_NODE_KIND(ExprStmt, "expression statement", struct { AstNode *expr; } ) \
|
AST_KIND(ExprStmt, "expression statement", struct { Ast *expr; } ) \
|
||||||
AST_NODE_KIND(TagStmt, "tag statement", struct { \
|
AST_KIND(TagStmt, "tag statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Token name; \
|
Token name; \
|
||||||
AstNode *stmt; \
|
Ast * stmt; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(AssignStmt, "assign statement", struct { \
|
AST_KIND(AssignStmt, "assign statement", struct { \
|
||||||
Token op; \
|
Token op; \
|
||||||
Array<AstNode *> lhs, rhs; \
|
Array<Ast *> lhs, rhs; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(IncDecStmt, "increment decrement statement", struct { \
|
AST_KIND(IncDecStmt, "increment decrement statement", struct { \
|
||||||
Token op; \
|
Token op; \
|
||||||
AstNode *expr; \
|
Ast *expr; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(_ComplexStmtBegin, "", struct {}) \
|
AST_KIND(_ComplexStmtBegin, "", struct {}) \
|
||||||
AST_NODE_KIND(BlockStmt, "block statement", struct { \
|
AST_KIND(BlockStmt, "block statement", struct { \
|
||||||
Array<AstNode *> stmts; \
|
Array<Ast *> stmts; \
|
||||||
Token open, close; \
|
Token open, close; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(IfStmt, "if statement", struct { \
|
AST_KIND(IfStmt, "if statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *init; \
|
Ast * init; \
|
||||||
AstNode *cond; \
|
Ast * cond; \
|
||||||
AstNode *body; \
|
Ast * body; \
|
||||||
AstNode *else_stmt; \
|
Ast * else_stmt; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(WhenStmt, "when statement", struct { \
|
AST_KIND(WhenStmt, "when statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *cond; \
|
Ast *cond; \
|
||||||
AstNode *body; \
|
Ast *body; \
|
||||||
AstNode *else_stmt; \
|
Ast *else_stmt; \
|
||||||
bool is_cond_determined; \
|
bool is_cond_determined; \
|
||||||
bool determined_cond; \
|
bool determined_cond; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(ReturnStmt, "return statement", struct { \
|
AST_KIND(ReturnStmt, "return statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Array<AstNode *> results; \
|
Array<Ast *> results; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(ForStmt, "for statement", struct { \
|
AST_KIND(ForStmt, "for statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *label; \
|
Ast *label; \
|
||||||
AstNode *init; \
|
Ast *init; \
|
||||||
AstNode *cond; \
|
Ast *cond; \
|
||||||
AstNode *post; \
|
Ast *post; \
|
||||||
AstNode *body; \
|
Ast *body; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(RangeStmt, "range statement", struct { \
|
AST_KIND(RangeStmt, "range statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *label; \
|
Ast *label; \
|
||||||
AstNode *val0; \
|
Ast *val0; \
|
||||||
AstNode *val1; \
|
Ast *val1; \
|
||||||
Token in_token; \
|
Token in_token; \
|
||||||
AstNode *expr; \
|
Ast *expr; \
|
||||||
AstNode *body; \
|
Ast *body; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(CaseClause, "case clause", struct { \
|
AST_KIND(CaseClause, "case clause", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Array<AstNode *> list; \
|
Array<Ast *> list; \
|
||||||
Array<AstNode *> stmts; \
|
Array<Ast *> stmts; \
|
||||||
Entity *implicit_entity; \
|
Entity *implicit_entity; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(SwitchStmt, "switch statement", struct { \
|
AST_KIND(SwitchStmt, "switch statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *label; \
|
Ast *label; \
|
||||||
AstNode *init; \
|
Ast *init; \
|
||||||
AstNode *tag; \
|
Ast *tag; \
|
||||||
AstNode *body; \
|
Ast *body; \
|
||||||
bool complete; \
|
bool complete; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(TypeSwitchStmt, "type switch statement", struct { \
|
AST_KIND(TypeSwitchStmt, "type switch statement", struct { \
|
||||||
Token token; \
|
|
||||||
AstNode *label; \
|
|
||||||
AstNode *tag; \
|
|
||||||
AstNode *body; \
|
|
||||||
bool complete; \
|
|
||||||
}) \
|
|
||||||
AST_NODE_KIND(DeferStmt, "defer statement", struct { Token token; AstNode *stmt; }) \
|
|
||||||
AST_NODE_KIND(BranchStmt, "branch statement", struct { Token token; AstNode *label; }) \
|
|
||||||
AST_NODE_KIND(UsingStmt, "using statement", struct { \
|
|
||||||
Token token; \
|
Token token; \
|
||||||
Array<AstNode *> list; \
|
Ast *label; \
|
||||||
|
Ast *tag; \
|
||||||
|
Ast *body; \
|
||||||
|
bool complete; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(PushContext, "context <- statement", struct { \
|
AST_KIND(DeferStmt, "defer statement", struct { Token token; Ast *stmt; }) \
|
||||||
Token token; \
|
AST_KIND(BranchStmt, "branch statement", struct { Token token; Ast *label; }) \
|
||||||
AstNode *expr; \
|
AST_KIND(UsingStmt, "using statement", struct { \
|
||||||
AstNode *body; \
|
|
||||||
}) \
|
|
||||||
AST_NODE_KIND(_ComplexStmtEnd, "", struct {}) \
|
|
||||||
AST_NODE_KIND(_StmtEnd, "", struct {}) \
|
|
||||||
AST_NODE_KIND(_DeclBegin, "", struct {}) \
|
|
||||||
AST_NODE_KIND(BadDecl, "bad declaration", struct { Token begin, end; }) \
|
|
||||||
AST_NODE_KIND(ForeignBlockDecl, "foreign block declaration", struct { \
|
|
||||||
Token token; \
|
|
||||||
AstNode * foreign_library; \
|
|
||||||
AstNode * body; \
|
|
||||||
Array<AstNode *> attributes; \
|
|
||||||
CommentGroup * docs; \
|
|
||||||
}) \
|
|
||||||
AST_NODE_KIND(Label, "label", struct { \
|
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *name; \
|
Array<Ast *> list; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(ValueDecl, "value declaration", struct { \
|
AST_KIND(PushContext, "context <- statement", struct { \
|
||||||
Array<AstNode *> names; \
|
Token token; \
|
||||||
AstNode * type; \
|
Ast *expr; \
|
||||||
Array<AstNode *> values; \
|
Ast *body; \
|
||||||
Array<AstNode *> attributes; \
|
|
||||||
CommentGroup * docs; \
|
|
||||||
CommentGroup * comment; \
|
|
||||||
bool is_using; \
|
|
||||||
bool is_mutable; \
|
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(PackageDecl, "package declaration", struct { \
|
AST_KIND(_ComplexStmtEnd, "", struct {}) \
|
||||||
|
AST_KIND(_StmtEnd, "", struct {}) \
|
||||||
|
AST_KIND(_DeclBegin, "", struct {}) \
|
||||||
|
AST_KIND(BadDecl, "bad declaration", struct { Token begin, end; }) \
|
||||||
|
AST_KIND(ForeignBlockDecl, "foreign block declaration", struct { \
|
||||||
|
Token token; \
|
||||||
|
Ast *foreign_library; \
|
||||||
|
Ast *body; \
|
||||||
|
Array<Ast *> attributes; \
|
||||||
|
CommentGroup *docs; \
|
||||||
|
}) \
|
||||||
|
AST_KIND(Label, "label", struct { \
|
||||||
|
Token token; \
|
||||||
|
Ast *name; \
|
||||||
|
}) \
|
||||||
|
AST_KIND(ValueDecl, "value declaration", struct { \
|
||||||
|
Array<Ast *> names; \
|
||||||
|
Ast * type; \
|
||||||
|
Array<Ast *> values; \
|
||||||
|
Array<Ast *> attributes; \
|
||||||
|
CommentGroup *docs; \
|
||||||
|
CommentGroup *comment; \
|
||||||
|
bool is_using; \
|
||||||
|
bool is_mutable; \
|
||||||
|
}) \
|
||||||
|
AST_KIND(PackageDecl, "package declaration", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Token name; \
|
Token name; \
|
||||||
CommentGroup *docs; \
|
CommentGroup *docs; \
|
||||||
CommentGroup *comment; \
|
CommentGroup *comment; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(ImportDecl, "import declaration", struct { \
|
AST_KIND(ImportDecl, "import declaration", struct { \
|
||||||
AstPackage *package; \
|
AstPackage *package; \
|
||||||
Token token; \
|
Token token; \
|
||||||
Token relpath; \
|
Token relpath; \
|
||||||
@@ -368,7 +368,7 @@ AST_NODE_KIND(_DeclBegin, "", struct {}) \
|
|||||||
CommentGroup *comment; \
|
CommentGroup *comment; \
|
||||||
bool is_using; \
|
bool is_using; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(ForeignImportDecl, "foreign import declaration", struct { \
|
AST_KIND(ForeignImportDecl, "foreign import declaration", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Token filepath; \
|
Token filepath; \
|
||||||
Token library_name; \
|
Token library_name; \
|
||||||
@@ -377,170 +377,170 @@ AST_NODE_KIND(_DeclBegin, "", struct {}) \
|
|||||||
CommentGroup *docs; \
|
CommentGroup *docs; \
|
||||||
CommentGroup *comment; \
|
CommentGroup *comment; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(_DeclEnd, "", struct {}) \
|
AST_KIND(_DeclEnd, "", struct {}) \
|
||||||
AST_NODE_KIND(Attribute, "attribute", struct { \
|
AST_KIND(Attribute, "attribute", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *type; \
|
Ast *type; \
|
||||||
Array<AstNode *> elems; \
|
Array<Ast *> elems; \
|
||||||
Token open, close; \
|
Token open, close; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(Field, "field", struct { \
|
AST_KIND(Field, "field", struct { \
|
||||||
Array<AstNode *> names; \
|
Array<Ast *> names; \
|
||||||
AstNode * type; \
|
Ast * type; \
|
||||||
AstNode * default_value; \
|
Ast * default_value; \
|
||||||
u32 flags; \
|
u32 flags; \
|
||||||
CommentGroup * docs; \
|
CommentGroup * docs; \
|
||||||
CommentGroup * comment; \
|
CommentGroup * comment; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(FieldList, "field list", struct { \
|
AST_KIND(FieldList, "field list", struct { \
|
||||||
|
Token token; \
|
||||||
|
Array<Ast *> list; \
|
||||||
|
}) \
|
||||||
|
AST_KIND(UnionField, "union field", struct { \
|
||||||
|
Ast *name; \
|
||||||
|
Ast *list; \
|
||||||
|
}) \
|
||||||
|
AST_KIND(_TypeBegin, "", struct {}) \
|
||||||
|
AST_KIND(TypeType, "type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Array<AstNode *> list; \
|
Ast *specialization; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(UnionField, "union field", struct { \
|
AST_KIND(HelperType, "helper type", struct { \
|
||||||
AstNode *name; \
|
|
||||||
AstNode *list; \
|
|
||||||
}) \
|
|
||||||
AST_NODE_KIND(_TypeBegin, "", struct {}) \
|
|
||||||
AST_NODE_KIND(TypeType, "type", struct { \
|
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *specialization; \
|
Ast *type; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(HelperType, "helper type", struct { \
|
AST_KIND(DistinctType, "distinct type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *type; \
|
Ast *type; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(DistinctType, "distinct type", struct { \
|
AST_KIND(PolyType, "polymorphic type", struct { \
|
||||||
Token token; \
|
|
||||||
AstNode *type; \
|
|
||||||
}) \
|
|
||||||
AST_NODE_KIND(PolyType, "polymorphic type", struct { \
|
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *type; \
|
Ast *type; \
|
||||||
AstNode *specialization; \
|
Ast *specialization; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(ProcType, "procedure type", struct { \
|
AST_KIND(ProcType, "procedure type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *params; \
|
Ast *params; \
|
||||||
AstNode *results; \
|
Ast *results; \
|
||||||
u64 tags; \
|
u64 tags; \
|
||||||
ProcCallingConvention calling_convention; \
|
ProcCallingConvention calling_convention; \
|
||||||
bool generic; \
|
bool generic; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(PointerType, "pointer type", struct { \
|
AST_KIND(PointerType, "pointer type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *type; \
|
Ast *type; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(ArrayType, "array type", struct { \
|
AST_KIND(ArrayType, "array type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *count; \
|
Ast *count; \
|
||||||
AstNode *elem; \
|
Ast *elem; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(DynamicArrayType, "dynamic array type", struct { \
|
AST_KIND(DynamicArrayType, "dynamic array type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *elem; \
|
Ast *elem; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(StructType, "struct type", struct { \
|
AST_KIND(StructType, "struct type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Array<AstNode *> fields; \
|
Array<Ast *> fields; \
|
||||||
isize field_count; \
|
isize field_count; \
|
||||||
AstNode * polymorphic_params; \
|
Ast *polymorphic_params; \
|
||||||
AstNode * align; \
|
Ast *align; \
|
||||||
bool is_packed; \
|
bool is_packed; \
|
||||||
bool is_raw_union; \
|
bool is_raw_union; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(UnionType, "union type", struct { \
|
AST_KIND(UnionType, "union type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Array<AstNode *> variants; \
|
Array<Ast *> variants; \
|
||||||
AstNode * align; \
|
Ast * align; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(EnumType, "enum type", struct { \
|
AST_KIND(EnumType, "enum type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode * base_type; \
|
Ast * base_type; \
|
||||||
Array<AstNode *> fields; /* FieldValue */ \
|
Array<Ast *> fields; /* FieldValue */ \
|
||||||
bool is_export; \
|
bool is_export; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(BitFieldType, "bit field type", struct { \
|
AST_KIND(BitFieldType, "bit field type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Array<AstNode *> fields; /* FieldValue with : */ \
|
Array<Ast *> fields; /* FieldValue with : */ \
|
||||||
AstNode * align; \
|
Ast * align; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(MapType, "map type", struct { \
|
AST_KIND(MapType, "map type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *count; \
|
Ast *count; \
|
||||||
AstNode *key; \
|
Ast *key; \
|
||||||
AstNode *value; \
|
Ast *value; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(_TypeEnd, "", struct {})
|
AST_KIND(_TypeEnd, "", struct {})
|
||||||
|
|
||||||
enum AstNodeKind {
|
enum AstKind {
|
||||||
AstNode_Invalid,
|
Ast_Invalid,
|
||||||
#define AST_NODE_KIND(_kind_name_, ...) GB_JOIN2(AstNode_, _kind_name_),
|
#define AST_KIND(_kind_name_, ...) GB_JOIN2(Ast_, _kind_name_),
|
||||||
AST_NODE_KINDS
|
AST_KINDS
|
||||||
#undef AST_NODE_KIND
|
#undef AST_KIND
|
||||||
AstNode_Count,
|
Ast_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
String const ast_node_strings[] = {
|
String const ast_strings[] = {
|
||||||
{cast(u8 *)"invalid node", gb_size_of("invalid node")},
|
{cast(u8 *)"invalid node", gb_size_of("invalid node")},
|
||||||
#define AST_NODE_KIND(_kind_name_, name, ...) {cast(u8 *)name, gb_size_of(name)-1},
|
#define AST_KIND(_kind_name_, name, ...) {cast(u8 *)name, gb_size_of(name)-1},
|
||||||
AST_NODE_KINDS
|
AST_KINDS
|
||||||
#undef AST_NODE_KIND
|
#undef AST_KIND
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define AST_NODE_KIND(_kind_name_, name, ...) typedef __VA_ARGS__ GB_JOIN2(AstNode, _kind_name_);
|
#define AST_KIND(_kind_name_, name, ...) typedef __VA_ARGS__ GB_JOIN2(Ast, _kind_name_);
|
||||||
AST_NODE_KINDS
|
AST_KINDS
|
||||||
#undef AST_NODE_KIND
|
#undef AST_KIND
|
||||||
|
|
||||||
|
|
||||||
isize const ast_node_sizes[] = {
|
isize const ast_variant_sizes[] = {
|
||||||
0,
|
0,
|
||||||
#define AST_NODE_KIND(_kind_name_, name, ...) gb_size_of(GB_JOIN2(AstNode, _kind_name_)),
|
#define AST_KIND(_kind_name_, name, ...) gb_size_of(GB_JOIN2(Ast, _kind_name_)),
|
||||||
AST_NODE_KINDS
|
AST_KINDS
|
||||||
#undef AST_NODE_KIND
|
#undef AST_KIND
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AstNode {
|
struct Ast {
|
||||||
AstNodeKind kind;
|
AstKind kind;
|
||||||
u32 stmt_state_flags;
|
u32 stmt_state_flags;
|
||||||
AstFile * file;
|
AstFile *file;
|
||||||
Scope * scope;
|
Scope * scope;
|
||||||
bool been_handled;
|
bool been_handled;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
#define AST_NODE_KIND(_kind_name_, name, ...) GB_JOIN2(AstNode, _kind_name_) _kind_name_;
|
#define AST_KIND(_kind_name_, name, ...) GB_JOIN2(Ast, _kind_name_) _kind_name_;
|
||||||
AST_NODE_KINDS
|
AST_KINDS
|
||||||
#undef AST_NODE_KIND
|
#undef AST_KIND
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define ast_node(n_, Kind_, node_) GB_JOIN2(AstNode, Kind_) *n_ = &(node_)->Kind_; GB_ASSERT_MSG((node_)->kind == GB_JOIN2(AstNode_, Kind_), \
|
#define ast_node(n_, Kind_, node_) GB_JOIN2(Ast, Kind_) *n_ = &(node_)->Kind_; GB_ASSERT_MSG((node_)->kind == GB_JOIN2(Ast_, Kind_), \
|
||||||
"expected '%.*s' got '%.*s'", \
|
"expected '%.*s' got '%.*s'", \
|
||||||
LIT(ast_node_strings[GB_JOIN2(AstNode_, Kind_)]), LIT(ast_node_strings[(node_)->kind]))
|
LIT(ast_strings[GB_JOIN2(Ast_, Kind_)]), LIT(ast_strings[(node_)->kind]))
|
||||||
#define case_ast_node(n_, Kind_, node_) case GB_JOIN2(AstNode_, Kind_): { ast_node(n_, Kind_, node_);
|
#define case_ast_node(n_, Kind_, node_) case GB_JOIN2(Ast_, Kind_): { ast_node(n_, Kind_, node_);
|
||||||
#ifndef case_end
|
#ifndef case_end
|
||||||
#define case_end } break;
|
#define case_end } break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
gb_inline bool is_ast_node_expr(AstNode *node) {
|
gb_inline bool is_ast_expr(Ast *node) {
|
||||||
return gb_is_between(node->kind, AstNode__ExprBegin+1, AstNode__ExprEnd-1);
|
return gb_is_between(node->kind, Ast__ExprBegin+1, Ast__ExprEnd-1);
|
||||||
}
|
}
|
||||||
gb_inline bool is_ast_node_stmt(AstNode *node) {
|
gb_inline bool is_ast_stmt(Ast *node) {
|
||||||
return gb_is_between(node->kind, AstNode__StmtBegin+1, AstNode__StmtEnd-1);
|
return gb_is_between(node->kind, Ast__StmtBegin+1, Ast__StmtEnd-1);
|
||||||
}
|
}
|
||||||
gb_inline bool is_ast_node_complex_stmt(AstNode *node) {
|
gb_inline bool is_ast_complex_stmt(Ast *node) {
|
||||||
return gb_is_between(node->kind, AstNode__ComplexStmtBegin+1, AstNode__ComplexStmtEnd-1);
|
return gb_is_between(node->kind, Ast__ComplexStmtBegin+1, Ast__ComplexStmtEnd-1);
|
||||||
}
|
}
|
||||||
gb_inline bool is_ast_node_decl(AstNode *node) {
|
gb_inline bool is_ast_decl(Ast *node) {
|
||||||
return gb_is_between(node->kind, AstNode__DeclBegin+1, AstNode__DeclEnd-1);
|
return gb_is_between(node->kind, Ast__DeclBegin+1, Ast__DeclEnd-1);
|
||||||
}
|
}
|
||||||
gb_inline bool is_ast_node_type(AstNode *node) {
|
gb_inline bool is_ast_type(Ast *node) {
|
||||||
return gb_is_between(node->kind, AstNode__TypeBegin+1, AstNode__TypeEnd-1);
|
return gb_is_between(node->kind, Ast__TypeBegin+1, Ast__TypeEnd-1);
|
||||||
}
|
}
|
||||||
gb_inline bool is_ast_node_when_stmt(AstNode *node) {
|
gb_inline bool is_ast_when_stmt(Ast *node) {
|
||||||
return node->kind == AstNode_WhenStmt;
|
return node->kind == Ast_WhenStmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_global Arena global_ast_arena = {};
|
gb_global Arena global_ast_arena = {};
|
||||||
@@ -550,4 +550,4 @@ gbAllocator ast_allocator(void) {
|
|||||||
return arena_allocator(arena);
|
return arena_allocator(arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *alloc_ast_node(AstFile *f, AstNodeKind kind);
|
Ast *alloc_ast_node(AstFile *f, AstKind kind);
|
||||||
|
|||||||
+5
-5
@@ -1,5 +1,5 @@
|
|||||||
struct Scope;
|
struct Scope;
|
||||||
struct AstNode;
|
struct Ast;
|
||||||
|
|
||||||
enum BasicKind {
|
enum BasicKind {
|
||||||
Basic_Invalid,
|
Basic_Invalid,
|
||||||
@@ -81,7 +81,7 @@ struct BasicType {
|
|||||||
|
|
||||||
struct TypeStruct {
|
struct TypeStruct {
|
||||||
Array<Entity *> fields;
|
Array<Entity *> fields;
|
||||||
AstNode *node;
|
Ast *node;
|
||||||
Scope * scope;
|
Scope * scope;
|
||||||
|
|
||||||
Array<i64> offsets;
|
Array<i64> offsets;
|
||||||
@@ -130,7 +130,7 @@ struct TypeStruct {
|
|||||||
TYPE_KIND(Struct, TypeStruct) \
|
TYPE_KIND(Struct, TypeStruct) \
|
||||||
TYPE_KIND(Enum, struct { \
|
TYPE_KIND(Enum, struct { \
|
||||||
Array<Entity *> fields; \
|
Array<Entity *> fields; \
|
||||||
AstNode *node; \
|
Ast *node; \
|
||||||
Scope * scope; \
|
Scope * scope; \
|
||||||
Entity * names; \
|
Entity * names; \
|
||||||
Type * base_type; \
|
Type * base_type; \
|
||||||
@@ -141,7 +141,7 @@ struct TypeStruct {
|
|||||||
}) \
|
}) \
|
||||||
TYPE_KIND(Union, struct { \
|
TYPE_KIND(Union, struct { \
|
||||||
Array<Type *> variants; \
|
Array<Type *> variants; \
|
||||||
AstNode *node; \
|
Ast *node; \
|
||||||
Scope * scope; \
|
Scope * scope; \
|
||||||
i64 variant_block_size; \
|
i64 variant_block_size; \
|
||||||
i64 custom_align; \
|
i64 custom_align; \
|
||||||
@@ -153,7 +153,7 @@ struct TypeStruct {
|
|||||||
bool are_offsets_set; \
|
bool are_offsets_set; \
|
||||||
}) \
|
}) \
|
||||||
TYPE_KIND(Proc, struct { \
|
TYPE_KIND(Proc, struct { \
|
||||||
AstNode *node; \
|
Ast *node; \
|
||||||
Scope * scope; \
|
Scope * scope; \
|
||||||
Type * params; /* Type_Tuple */ \
|
Type * params; /* Type_Tuple */ \
|
||||||
Type * results; /* Type_Tuple */ \
|
Type * results; /* Type_Tuple */ \
|
||||||
|
|||||||
Reference in New Issue
Block a user