mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Foreign context cleanup
This commit is contained in:
+4
-4
@@ -1669,8 +1669,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
|
|
||||||
CheckerContext prev_context = c->context;
|
CheckerContext prev_context = c->context;
|
||||||
if (ok) {
|
if (ok) {
|
||||||
c->context.curr_foreign_library = foreign_library;
|
c->context.foreign_context.curr_library = foreign_library;
|
||||||
c->context.default_foreign_cc = ProcCC_CDecl;
|
c->context.foreign_context.default_cc = ProcCC_CDecl;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_foreign_block_decl_attributes(c, fb);
|
check_foreign_block_decl_attributes(c, fb);
|
||||||
@@ -1763,7 +1763,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
entity = make_entity_variable(c->allocator, c->context.scope, token, nullptr, false);
|
entity = make_entity_variable(c->allocator, c->context.scope, token, nullptr, false);
|
||||||
entity->identifier = name;
|
entity->identifier = name;
|
||||||
|
|
||||||
AstNode *fl = c->context.curr_foreign_library;
|
AstNode *fl = c->context.foreign_context.curr_library;
|
||||||
if (fl != nullptr) {
|
if (fl != nullptr) {
|
||||||
GB_ASSERT(fl->kind == AstNode_Ident);
|
GB_ASSERT(fl->kind == AstNode_Ident);
|
||||||
entity->Variable.is_foreign = true;
|
entity->Variable.is_foreign = true;
|
||||||
@@ -1850,7 +1850,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
add_entity(c, c->context.scope, e->identifier, e);
|
add_entity(c, c->context.scope, e->identifier, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((vd->flags & VarDeclFlag_using) != 0) {
|
if (vd->is_using != 0) {
|
||||||
Token token = ast_node_token(node);
|
Token token = ast_node_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");
|
||||||
|
|||||||
+3
-3
@@ -82,7 +82,7 @@ void check_struct_field_decl(Checker *c, AstNode *decl, Array<Entity *> *fields,
|
|||||||
|
|
||||||
if (!vd->is_mutable) return;
|
if (!vd->is_mutable) return;
|
||||||
|
|
||||||
bool is_using = (vd->flags&VarDeclFlag_using) != 0;
|
bool is_using = vd->is_using;
|
||||||
|
|
||||||
if (is_using && vd->names.count > 1) {
|
if (is_using && vd->names.count > 1) {
|
||||||
error(vd->names[0], "Cannot apply `using` to more than one of the same type");
|
error(vd->names[0], "Cannot apply `using` to more than one of the same type");
|
||||||
@@ -1891,8 +1891,8 @@ bool check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array
|
|||||||
ProcCallingConvention cc = pt->calling_convention;
|
ProcCallingConvention cc = pt->calling_convention;
|
||||||
if (cc == ProcCC_ForeignBlockDefault) {
|
if (cc == ProcCC_ForeignBlockDefault) {
|
||||||
cc = ProcCC_CDecl;
|
cc = ProcCC_CDecl;
|
||||||
if (c->context.default_foreign_cc > 0) {
|
if (c->context.foreign_context.default_cc > 0) {
|
||||||
cc = c->context.default_foreign_cc;
|
cc = c->context.foreign_context.default_cc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GB_ASSERT(cc > 0);
|
GB_ASSERT(cc > 0);
|
||||||
|
|||||||
+23
-22
@@ -411,7 +411,12 @@ GB_COMPARE_PROC(ast_node_cmp) {
|
|||||||
return token_pos_cmp(i.pos, j.pos);
|
return token_pos_cmp(i.pos, j.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ForeignContext {
|
||||||
|
AstNode * curr_library;
|
||||||
|
ProcCallingConvention default_cc;
|
||||||
|
String link_prefix;
|
||||||
|
bool in_export;
|
||||||
|
};
|
||||||
|
|
||||||
struct CheckerContext {
|
struct CheckerContext {
|
||||||
Scope * file_scope;
|
Scope * file_scope;
|
||||||
@@ -422,11 +427,8 @@ struct CheckerContext {
|
|||||||
String proc_name;
|
String proc_name;
|
||||||
Type * type_hint;
|
Type * type_hint;
|
||||||
DeclInfo * curr_proc_decl;
|
DeclInfo * curr_proc_decl;
|
||||||
AstNode * curr_foreign_library;
|
ForeignContext foreign_context;
|
||||||
ProcCallingConvention default_foreign_cc;
|
|
||||||
String foreign_link_prefix;
|
|
||||||
|
|
||||||
bool in_foreign_export;
|
|
||||||
bool collect_delayed_decls;
|
bool collect_delayed_decls;
|
||||||
bool allow_polymorphic_types;
|
bool allow_polymorphic_types;
|
||||||
bool no_polymorphic_errors;
|
bool no_polymorphic_errors;
|
||||||
@@ -1916,7 +1918,7 @@ void check_foreign_block_decl_attributes(Checker *c, AstNodeForeignBlockDecl *fb
|
|||||||
if (cc == ProcCC_Invalid) {
|
if (cc == ProcCC_Invalid) {
|
||||||
error(elem, "Unknown procedure calling convention: `%.*s`\n", LIT(ev.value_string));
|
error(elem, "Unknown procedure calling convention: `%.*s`\n", LIT(ev.value_string));
|
||||||
} else {
|
} else {
|
||||||
c->context.default_foreign_cc = cc;
|
c->context.foreign_context.default_cc = cc;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error(elem, "Expected a string value for `%.*s`", LIT(name));
|
error(elem, "Expected a string value for `%.*s`", LIT(name));
|
||||||
@@ -1927,7 +1929,7 @@ void check_foreign_block_decl_attributes(Checker *c, AstNodeForeignBlockDecl *fb
|
|||||||
if (!is_foreign_name_valid(link_prefix)) {
|
if (!is_foreign_name_valid(link_prefix)) {
|
||||||
error(elem, "Invalid link prefix: `%.*s`\n", LIT(link_prefix));
|
error(elem, "Invalid link prefix: `%.*s`\n", LIT(link_prefix));
|
||||||
} else {
|
} else {
|
||||||
c->context.foreign_link_prefix = link_prefix;
|
c->context.foreign_context.link_prefix = link_prefix;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error(elem, "Expected a string value for `%.*s`", LIT(name));
|
error(elem, "Expected a string value for `%.*s`", LIT(name));
|
||||||
@@ -2053,20 +2055,20 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
|
|||||||
Entity *e = make_entity_variable(c->allocator, c->context.scope, name->Ident.token, nullptr, false);
|
Entity *e = make_entity_variable(c->allocator, c->context.scope, name->Ident.token, nullptr, false);
|
||||||
e->identifier = name;
|
e->identifier = name;
|
||||||
|
|
||||||
if (vd->flags & VarDeclFlag_using) {
|
if (vd->is_using) {
|
||||||
vd->flags &= ~VarDeclFlag_using; // NOTE(bill): This error will be only caught once
|
vd->is_using = false; // NOTE(bill): This error will be only caught once
|
||||||
error(name, "`using` is not allowed at the file scope");
|
error(name, "`using` is not allowed at the file scope");
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *fl = c->context.curr_foreign_library;
|
AstNode *fl = c->context.foreign_context.curr_library;
|
||||||
if (fl != nullptr) {
|
if (fl != nullptr) {
|
||||||
GB_ASSERT(fl->kind == AstNode_Ident);
|
GB_ASSERT(fl->kind == AstNode_Ident);
|
||||||
e->Variable.is_foreign = true;
|
e->Variable.is_foreign = true;
|
||||||
e->Variable.foreign_library_ident = fl;
|
e->Variable.foreign_library_ident = fl;
|
||||||
|
|
||||||
e->Variable.link_prefix = c->context.foreign_link_prefix;
|
e->Variable.link_prefix = c->context.foreign_context.link_prefix;
|
||||||
|
|
||||||
} else if (c->context.in_foreign_export) {
|
} else if (c->context.foreign_context.in_export) {
|
||||||
e->Variable.is_export = true;
|
e->Variable.is_export = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2105,7 +2107,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
|
|||||||
|
|
||||||
Token token = name->Ident.token;
|
Token token = name->Ident.token;
|
||||||
|
|
||||||
AstNode *fl = c->context.curr_foreign_library;
|
AstNode *fl = c->context.foreign_context.curr_library;
|
||||||
DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, c->context.decl);
|
DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, c->context.decl);
|
||||||
Entity *e = nullptr;
|
Entity *e = nullptr;
|
||||||
|
|
||||||
@@ -2135,16 +2137,16 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
|
|||||||
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;
|
||||||
if (c->context.default_foreign_cc > 0) {
|
if (c->context.foreign_context.default_cc > 0) {
|
||||||
cc = c->context.default_foreign_cc;
|
cc = c->context.foreign_context.default_cc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e->Procedure.link_prefix = c->context.foreign_link_prefix;
|
e->Procedure.link_prefix = c->context.foreign_context.link_prefix;
|
||||||
|
|
||||||
GB_ASSERT(cc != ProcCC_Invalid);
|
GB_ASSERT(cc != ProcCC_Invalid);
|
||||||
pl->type->ProcType.calling_convention = cc;
|
pl->type->ProcType.calling_convention = cc;
|
||||||
|
|
||||||
} else if (c->context.in_foreign_export) {
|
} else if (c->context.foreign_context.in_export) {
|
||||||
e->Procedure.is_export = true;
|
e->Procedure.is_export = true;
|
||||||
}
|
}
|
||||||
d->proc_lit = init;
|
d->proc_lit = init;
|
||||||
@@ -2157,7 +2159,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
|
|||||||
e->identifier = name;
|
e->identifier = name;
|
||||||
|
|
||||||
if (e->kind != Entity_Procedure) {
|
if (e->kind != Entity_Procedure) {
|
||||||
if (fl != nullptr || c->context.in_foreign_export) {
|
if (fl != nullptr || c->context.foreign_context.in_export) {
|
||||||
AstNodeKind kind = init->kind;
|
AstNodeKind 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_node_strings[kind]));
|
||||||
if (kind == AstNode_ProcType) {
|
if (kind == AstNode_ProcType) {
|
||||||
@@ -2182,15 +2184,14 @@ void check_add_foreign_block_decl(Checker *c, AstNode *decl) {
|
|||||||
|
|
||||||
AstNode *foreign_library = fb->foreign_library;
|
AstNode *foreign_library = fb->foreign_library;
|
||||||
|
|
||||||
|
|
||||||
CheckerContext prev_context = c->context;
|
CheckerContext prev_context = c->context;
|
||||||
if (foreign_library->kind == AstNode_Ident) {
|
if (foreign_library->kind == AstNode_Ident) {
|
||||||
c->context.curr_foreign_library = foreign_library;
|
c->context.foreign_context.curr_library = foreign_library;
|
||||||
} else if (foreign_library->kind == AstNode_Implicit && foreign_library->Implicit.kind == Token_export) {
|
} else if (foreign_library->kind == AstNode_Implicit && foreign_library->Implicit.kind == Token_export) {
|
||||||
c->context.in_foreign_export = true;
|
c->context.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`");
|
||||||
c->context.curr_foreign_library = nullptr;
|
c->context.foreign_context.curr_library = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_foreign_block_decl_attributes(c, fb);
|
check_foreign_block_decl_attributes(c, fb);
|
||||||
|
|||||||
+2
-39
@@ -115,10 +115,6 @@ enum ProcCallingConvention {
|
|||||||
ProcCC_ForeignBlockDefault = -1,
|
ProcCC_ForeignBlockDefault = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum VarDeclFlag {
|
|
||||||
VarDeclFlag_using = 1<<0,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum StmtStateFlag {
|
enum StmtStateFlag {
|
||||||
StmtStateFlag_bounds_check = 1<<0,
|
StmtStateFlag_bounds_check = 1<<0,
|
||||||
StmtStateFlag_no_bounds_check = 1<<1,
|
StmtStateFlag_no_bounds_check = 1<<1,
|
||||||
@@ -347,7 +343,7 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
|
|||||||
Array<AstNode *> names; \
|
Array<AstNode *> names; \
|
||||||
AstNode * type; \
|
AstNode * type; \
|
||||||
Array<AstNode *> values; \
|
Array<AstNode *> values; \
|
||||||
u64 flags; \
|
bool is_using; \
|
||||||
bool is_mutable; \
|
bool is_mutable; \
|
||||||
bool been_handled; \
|
bool been_handled; \
|
||||||
Array<AstNode *> attributes; \
|
Array<AstNode *> attributes; \
|
||||||
@@ -3517,39 +3513,6 @@ AstNode *parse_struct_field_list(AstFile *f, isize *name_count_) {
|
|||||||
AstNode *params = parse_field_list(f, &total_name_count, FieldFlag_Struct, Token_CloseBrace, true, false);
|
AstNode *params = parse_field_list(f, &total_name_count, FieldFlag_Struct, Token_CloseBrace, true, false);
|
||||||
if (name_count_) *name_count_ = total_name_count;
|
if (name_count_) *name_count_ = total_name_count;
|
||||||
return params;
|
return params;
|
||||||
|
|
||||||
#if 0
|
|
||||||
while (f->curr_token.kind != Token_CloseBrace &&
|
|
||||||
f->curr_token.kind != Token_EOF) {
|
|
||||||
AstNode *decl = parse_stmt(f);
|
|
||||||
switch (decl->kind) {
|
|
||||||
case AstNode_EmptyStmt:
|
|
||||||
case AstNode_BadStmt:
|
|
||||||
case AstNode_BadDecl:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case_ast_node(vd, ValueDecl, decl);
|
|
||||||
if (vd->flags&VarDeclFlag_thread_local) {
|
|
||||||
vd->flags &= ~VarDeclFlag_thread_local;
|
|
||||||
syntax_error(decl, "Field values cannot be #thread_local");
|
|
||||||
}
|
|
||||||
array_add(&decls, decl);
|
|
||||||
total_name_count += vd->names.count;
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case AstNode_WhenStmt:
|
|
||||||
array_add(&decls, decl);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
syntax_error(decl, "Expected a value declaration, got %.*s", LIT(ast_node_strings[decl->kind]));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name_count_) *name_count_ = total_name_count;
|
|
||||||
return ast_field_list(f, start_token, decls);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow, bool allow_default_parameters, bool allow_type_token) {
|
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow, bool allow_default_parameters, bool allow_type_token) {
|
||||||
@@ -4549,7 +4512,7 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
syntax_error(token, "`using` may only be applied to variable declarations");
|
syntax_error(token, "`using` may only be applied to variable declarations");
|
||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
decl->ValueDecl.flags |= VarDeclFlag_using;
|
decl->ValueDecl.is_using = true;
|
||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user