mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
static variable declarations (Experimental)
This commit is contained in:
@@ -1667,6 +1667,8 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
|
|||||||
if (!is_blank_ident(str)) {
|
if (!is_blank_ident(str)) {
|
||||||
found = scope_lookup_current(ctx->scope, str);
|
found = scope_lookup_current(ctx->scope, str);
|
||||||
new_name_count += 1;
|
new_name_count += 1;
|
||||||
|
} else if (vd->is_static) {
|
||||||
|
error(name, "'static' is now allowed to be applied to '_'");
|
||||||
}
|
}
|
||||||
if (found == nullptr) {
|
if (found == nullptr) {
|
||||||
entity = alloc_entity_variable(ctx->scope, token, nullptr, false);
|
entity = alloc_entity_variable(ctx->scope, token, nullptr, false);
|
||||||
@@ -1678,6 +1680,9 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
|
|||||||
entity->Variable.is_foreign = true;
|
entity->Variable.is_foreign = true;
|
||||||
entity->Variable.foreign_library_ident = fl;
|
entity->Variable.foreign_library_ident = fl;
|
||||||
}
|
}
|
||||||
|
if (vd->is_static) {
|
||||||
|
entity->flags |= EntityFlag_Static;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
TokenPos pos = found->token.pos;
|
TokenPos pos = found->token.pos;
|
||||||
error(token,
|
error(token,
|
||||||
@@ -1780,6 +1785,17 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
|
|||||||
} else {
|
} else {
|
||||||
map_set(fp, key, e);
|
map_set(fp, key, e);
|
||||||
}
|
}
|
||||||
|
} else if (e->flags & EntityFlag_Static) {
|
||||||
|
if (vd->values.count > 0) {
|
||||||
|
if (entity_count != vd->values.count) {
|
||||||
|
error(e->token, "A static variable declaration with a default value must be constant");
|
||||||
|
} else {
|
||||||
|
Ast *value = vd->values[i];
|
||||||
|
if (value->tav.mode != Addressing_Constant) {
|
||||||
|
error(e->token, "A static variable declaration with a default value must be constant");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
add_entity(ctx->checker, ctx->scope, e->identifier, e);
|
add_entity(ctx->checker, ctx->scope, e->identifier, e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2282,6 +2282,10 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
|||||||
e->flags |= EntityFlag_NotExported;
|
e->flags |= EntityFlag_NotExported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vd->is_static) {
|
||||||
|
e->flags |= EntityFlag_Static;
|
||||||
|
}
|
||||||
|
|
||||||
if (vd->is_using) {
|
if (vd->is_using) {
|
||||||
vd->is_using = false; // 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");
|
||||||
@@ -2386,6 +2390,14 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
|||||||
e->flags |= EntityFlag_NotExported;
|
e->flags |= EntityFlag_NotExported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vd->is_static) {
|
||||||
|
if (e->kind == Entity_Constant) {
|
||||||
|
e->flags |= EntityFlag_Static;
|
||||||
|
} else {
|
||||||
|
error(name, "'static' is not allowed on this constant value declaration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (vd->is_using) {
|
if (vd->is_using) {
|
||||||
if (e->kind == Entity_TypeName && init->kind == Ast_EnumType) {
|
if (e->kind == Entity_TypeName && init->kind == Ast_EnumType) {
|
||||||
d->is_using = true;
|
d->is_using = true;
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ enum EntityFlag {
|
|||||||
EntityFlag_PolyConst = 1<<13,
|
EntityFlag_PolyConst = 1<<13,
|
||||||
EntityFlag_NotExported = 1<<14,
|
EntityFlag_NotExported = 1<<14,
|
||||||
|
|
||||||
|
EntityFlag_Static = 1<<16,
|
||||||
|
|
||||||
EntityFlag_CVarArg = 1<<20,
|
EntityFlag_CVarArg = 1<<20,
|
||||||
EntityFlag_AutoCast = 1<<21,
|
EntityFlag_AutoCast = 1<<21,
|
||||||
|
|||||||
+43
@@ -405,6 +405,7 @@ struct irValueGlobal {
|
|||||||
bool is_constant;
|
bool is_constant;
|
||||||
bool is_export;
|
bool is_export;
|
||||||
bool is_private;
|
bool is_private;
|
||||||
|
bool is_internal;
|
||||||
String thread_local_model;
|
String thread_local_model;
|
||||||
bool is_foreign;
|
bool is_foreign;
|
||||||
bool is_unnamed_addr;
|
bool is_unnamed_addr;
|
||||||
@@ -7941,6 +7942,44 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
|
|||||||
case_ast_node(vd, ValueDecl, node);
|
case_ast_node(vd, ValueDecl, node);
|
||||||
if (vd->is_mutable) {
|
if (vd->is_mutable) {
|
||||||
irModule *m = proc->module;
|
irModule *m = proc->module;
|
||||||
|
|
||||||
|
if (vd->is_static) {
|
||||||
|
for_array(i, vd->names) {
|
||||||
|
irValue *value = nullptr;
|
||||||
|
if (vd->values.count > 0) {
|
||||||
|
GB_ASSERT(vd->names.count == vd->values.count);
|
||||||
|
Ast *ast_value = vd->values[i];
|
||||||
|
GB_ASSERT(ast_value->tav.mode == Addressing_Constant ||
|
||||||
|
ast_value->tav.mode == Addressing_Invalid);
|
||||||
|
|
||||||
|
value = ir_add_module_constant(m, ast_value->tav.type, ast_value->tav.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast *ident = vd->names[i];
|
||||||
|
GB_ASSERT(!is_blank_ident(ident));
|
||||||
|
Entity *e = entity_of_ident(ident);
|
||||||
|
GB_ASSERT(e->flags & EntityFlag_Static);
|
||||||
|
String name = e->token.string;
|
||||||
|
HashKey key = hash_string(name);
|
||||||
|
|
||||||
|
String mangled_name = {};
|
||||||
|
{
|
||||||
|
gbString str = gb_string_make_length(heap_allocator(), proc->name.text, proc->name.len);
|
||||||
|
str = gb_string_appendc(str, "-");
|
||||||
|
str = gb_string_append_fmt(str, ".%.*s-%llu", LIT(name), cast(long long)e->id);
|
||||||
|
mangled_name.text = cast(u8 *)str;
|
||||||
|
mangled_name.len = gb_string_length(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
irValue *g = ir_value_global(e, value);
|
||||||
|
g->Global.name = mangled_name;
|
||||||
|
g->Global.is_internal = true;
|
||||||
|
ir_module_add_value(proc->module, e, g);
|
||||||
|
map_set(&proc->module->members, key, g);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
|
||||||
defer (gb_temp_arena_memory_end(tmp));
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
|
|
||||||
@@ -10143,6 +10182,10 @@ void ir_gen_tree(irGen *s) {
|
|||||||
ir_add_foreign_library_path(m, fl);
|
ir_add_foreign_library_path(m, fl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e->flags & EntityFlag_Static) {
|
||||||
|
var->var->Global.is_internal = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (var->init != nullptr) {
|
if (var->init != nullptr) {
|
||||||
Type *t = type_deref(ir_type(var->var));
|
Type *t = type_deref(ir_type(var->var));
|
||||||
|
|
||||||
|
|||||||
@@ -2233,6 +2233,8 @@ void print_llvm_ir(irGen *ir) {
|
|||||||
|
|
||||||
if (g->is_private) {
|
if (g->is_private) {
|
||||||
ir_write_string(f, str_lit("private "));
|
ir_write_string(f, str_lit("private "));
|
||||||
|
} else if (g->is_internal) {
|
||||||
|
ir_write_string(f, str_lit("internal "));
|
||||||
}
|
}
|
||||||
if (g->is_constant) {
|
if (g->is_constant) {
|
||||||
if (g->is_unnamed_addr) {
|
if (g->is_unnamed_addr) {
|
||||||
|
|||||||
+28
-4
@@ -3810,6 +3810,34 @@ Ast *parse_stmt(AstFile *f) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Token_static: {
|
||||||
|
CommentGroup *docs = f->lead_comment;
|
||||||
|
Token token = expect_token(f, Token_static);
|
||||||
|
|
||||||
|
Ast *decl = nullptr;
|
||||||
|
Array<Ast *> list = parse_lhs_expr_list(f);
|
||||||
|
if (list.count == 0) {
|
||||||
|
syntax_error(token, "Illegal use of 'static' statement");
|
||||||
|
expect_semicolon(f, nullptr);
|
||||||
|
return ast_bad_stmt(f, token, f->curr_token);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect_token_after(f, Token_Colon, "identifier list");
|
||||||
|
decl = parse_value_decl(f, list, docs);
|
||||||
|
|
||||||
|
if (decl != nullptr && decl->kind == Ast_ValueDecl) {
|
||||||
|
if (decl->ValueDecl.is_mutable) {
|
||||||
|
decl->ValueDecl.is_static = true;
|
||||||
|
} else {
|
||||||
|
error(token, "'static' may only be currently used with variable declaration");
|
||||||
|
}
|
||||||
|
return decl;
|
||||||
|
}
|
||||||
|
|
||||||
|
syntax_error(token, "Illegal use of 'static' statement");
|
||||||
|
return ast_bad_stmt(f, token, f->curr_token);
|
||||||
|
} break;
|
||||||
|
|
||||||
case Token_using: {
|
case Token_using: {
|
||||||
CommentGroup *docs = f->lead_comment;
|
CommentGroup *docs = f->lead_comment;
|
||||||
Token token = expect_token(f, Token_using);
|
Token token = expect_token(f, Token_using);
|
||||||
@@ -3833,10 +3861,6 @@ Ast *parse_stmt(AstFile *f) {
|
|||||||
decl = parse_value_decl(f, list, docs);
|
decl = parse_value_decl(f, list, docs);
|
||||||
|
|
||||||
if (decl != nullptr && decl->kind == Ast_ValueDecl) {
|
if (decl != nullptr && decl->kind == Ast_ValueDecl) {
|
||||||
// if (!decl->ValueDecl.is_mutable) {
|
|
||||||
// syntax_error(token, "'using' may only be applied to variable declarations");
|
|
||||||
// return decl;
|
|
||||||
// }
|
|
||||||
decl->ValueDecl.is_using = true;
|
decl->ValueDecl.is_using = true;
|
||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -374,6 +374,7 @@ AST_KIND(_DeclBegin, "", bool) \
|
|||||||
Array<Ast *> attributes; \
|
Array<Ast *> attributes; \
|
||||||
CommentGroup *docs; \
|
CommentGroup *docs; \
|
||||||
CommentGroup *comment; \
|
CommentGroup *comment; \
|
||||||
|
bool is_static; \
|
||||||
bool is_using; \
|
bool is_using; \
|
||||||
bool is_mutable; \
|
bool is_mutable; \
|
||||||
}) \
|
}) \
|
||||||
|
|||||||
+1
-1
@@ -108,7 +108,7 @@ TOKEN_KIND(Token__KeywordBegin, ""), \
|
|||||||
TOKEN_KIND(Token_bit_field, "bit_field"), \
|
TOKEN_KIND(Token_bit_field, "bit_field"), \
|
||||||
TOKEN_KIND(Token_bit_set, "bit_set"), \
|
TOKEN_KIND(Token_bit_set, "bit_set"), \
|
||||||
TOKEN_KIND(Token_map, "map"), \
|
TOKEN_KIND(Token_map, "map"), \
|
||||||
TOKEN_KIND(Token_static, "static"), \
|
TOKEN_KIND(Token_static, "static"), \
|
||||||
TOKEN_KIND(Token_dynamic, "dynamic"), \
|
TOKEN_KIND(Token_dynamic, "dynamic"), \
|
||||||
TOKEN_KIND(Token_auto_cast, "auto_cast"), \
|
TOKEN_KIND(Token_auto_cast, "auto_cast"), \
|
||||||
TOKEN_KIND(Token_cast, "cast"), \
|
TOKEN_KIND(Token_cast, "cast"), \
|
||||||
|
|||||||
Reference in New Issue
Block a user