mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-29 19:00:06 +00:00
Prefix type and let to replace immutable
This commit is contained in:
@@ -178,6 +178,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
|
||||
if (init != NULL) {
|
||||
check_expr_or_type(c, &operand, init);
|
||||
}
|
||||
#if 0
|
||||
if (operand.mode == Addressing_Type) {
|
||||
e->kind = Entity_TypeName;
|
||||
|
||||
@@ -186,6 +187,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
|
||||
check_type_decl(c, e, d->type_expr, named_type);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
check_init_constant(c, e, &operand);
|
||||
|
||||
|
||||
+1
-1
@@ -1538,7 +1538,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
case_ast_node(vd, ValueDecl, node);
|
||||
GB_ASSERT(!c->context.scope->is_file);
|
||||
if (vd->token.kind != Token_var) {
|
||||
if (vd->token.kind == Token_const) {
|
||||
// NOTE(bill): Handled elsewhere
|
||||
} else {
|
||||
Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count);
|
||||
|
||||
+43
-22
@@ -1451,7 +1451,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
|
||||
case_end;
|
||||
|
||||
case_ast_node(vd, ValueDecl, decl);
|
||||
if (vd->token.kind == Token_var) {
|
||||
if (vd->token.kind != Token_const) {
|
||||
if (!c->context.scope->is_file) {
|
||||
// NOTE(bill): local scope -> handle later and in order
|
||||
break;
|
||||
@@ -1527,30 +1527,30 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
|
||||
Entity *e = NULL;
|
||||
|
||||
AstNode *up_init = unparen_expr(init);
|
||||
if (up_init != NULL && is_ast_node_type(up_init)) {
|
||||
AstNode *type = up_init;
|
||||
e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL);
|
||||
// TODO(bill): What if vd->type != NULL??? How to handle this case?
|
||||
d->type_expr = type;
|
||||
d->init_expr = type;
|
||||
} else if (up_init != NULL && up_init->kind == AstNode_Alias) {
|
||||
#if 1
|
||||
error_node(up_init, "#alias declarations are not yet supported");
|
||||
continue;
|
||||
#else
|
||||
e = make_entity_alias(c->allocator, d->scope, name->Ident, NULL, EntityAlias_Invalid, NULL);
|
||||
d->type_expr = vd->type;
|
||||
d->init_expr = up_init->Alias.expr;
|
||||
#endif
|
||||
// } else if (init != NULL && up_init->kind == AstNode_ProcLit) {
|
||||
// e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags);
|
||||
// d->proc_lit = up_init;
|
||||
// d->type_expr = vd->type;
|
||||
} else {
|
||||
// if (up_init != NULL && is_ast_node_type(up_init)) {
|
||||
// AstNode *type = up_init;
|
||||
// e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL);
|
||||
// // TODO(bill): What if vd->type != NULL??? How to handle this case?
|
||||
// d->type_expr = type;
|
||||
// d->init_expr = type;
|
||||
// } else if (up_init != NULL && up_init->kind == AstNode_Alias) {
|
||||
// #if 1
|
||||
// error_node(up_init, "#alias declarations are not yet supported");
|
||||
// continue;
|
||||
// #else
|
||||
// e = make_entity_alias(c->allocator, d->scope, name->Ident, NULL, EntityAlias_Invalid, NULL);
|
||||
// d->type_expr = vd->type;
|
||||
// d->init_expr = up_init->Alias.expr;
|
||||
// #endif
|
||||
// // } else if (init != NULL && up_init->kind == AstNode_ProcLit) {
|
||||
// // e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags);
|
||||
// // d->proc_lit = up_init;
|
||||
// // d->type_expr = vd->type;
|
||||
// } else {
|
||||
e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, empty_exact_value);
|
||||
d->type_expr = vd->type;
|
||||
d->init_expr = init;
|
||||
}
|
||||
// }
|
||||
GB_ASSERT(e != NULL);
|
||||
e->identifier = name;
|
||||
|
||||
@@ -1579,6 +1579,27 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
|
||||
add_entity_and_decl_info(c, name, e, d);
|
||||
case_end;
|
||||
|
||||
case_ast_node(td, TypeDecl, decl);
|
||||
AstNode *name = td->name;
|
||||
if (name->kind != AstNode_Ident) {
|
||||
error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, c->context.decl);
|
||||
Entity *e = NULL;
|
||||
|
||||
AstNode *type = unparen_expr(td->type);
|
||||
e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL);
|
||||
// TODO(bill): What if vd->type != NULL??? How to handle this case?
|
||||
d->type_expr = type;
|
||||
d->init_expr = type;
|
||||
|
||||
e->identifier = name;
|
||||
add_entity_and_decl_info(c, name, e, d);
|
||||
case_end;
|
||||
|
||||
case_ast_node(id, ImportDecl, decl);
|
||||
if (!c->context.scope->is_file) {
|
||||
if (id->is_import) {
|
||||
|
||||
+23
-25
@@ -5813,7 +5813,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(vd, ValueDecl, node);
|
||||
if (vd->token.kind == Token_var) {
|
||||
if (vd->token.kind != Token_const) {
|
||||
irModule *m = proc->module;
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
|
||||
|
||||
@@ -5862,30 +5862,6 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
} else {
|
||||
for_array(i, vd->names) {
|
||||
AstNode *ident = vd->names[i];
|
||||
GB_ASSERT(ident->kind == AstNode_Ident);
|
||||
Entity *e = entity_of_ident(proc->module->info, ident);
|
||||
GB_ASSERT(e != NULL);
|
||||
switch (e->kind) {
|
||||
case Entity_TypeName: {
|
||||
// NOTE(bill): Generate a new name
|
||||
// parent_proc.name-guid
|
||||
String ts_name = e->token.string;
|
||||
isize name_len = proc->name.len + 1 + ts_name.len + 1 + 10 + 1;
|
||||
u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
|
||||
i32 guid = cast(i32)proc->module->members.entries.count;
|
||||
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s-%d", LIT(proc->name), LIT(ts_name), guid);
|
||||
String name = make_string(name_text, name_len-1);
|
||||
|
||||
irValue *value = ir_value_type_name(proc->module->allocator,
|
||||
name, e->type);
|
||||
map_set(&proc->module->entity_names, hash_pointer(e), name);
|
||||
ir_gen_global_type_name(proc->module, e, name);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
|
||||
@@ -5960,6 +5936,28 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(td, TypeDecl, node);
|
||||
AstNode *ident = td->name;
|
||||
GB_ASSERT(ident->kind == AstNode_Ident);
|
||||
Entity *e = entity_of_ident(proc->module->info, ident);
|
||||
GB_ASSERT(e != NULL);
|
||||
if (e->kind == Entity_TypeName) {
|
||||
// NOTE(bill): Generate a new name
|
||||
// parent_proc.name-guid
|
||||
String ts_name = e->token.string;
|
||||
isize name_len = proc->name.len + 1 + ts_name.len + 1 + 10 + 1;
|
||||
u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
|
||||
i32 guid = cast(i32)proc->module->members.entries.count;
|
||||
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s-%d", LIT(proc->name), LIT(ts_name), guid);
|
||||
String name = make_string(name_text, name_len-1);
|
||||
|
||||
irValue *value = ir_value_type_name(proc->module->allocator,
|
||||
name, e->type);
|
||||
map_set(&proc->module->entity_names, hash_pointer(e), name);
|
||||
ir_gen_global_type_name(proc->module, e, name);
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(as, AssignStmt, node);
|
||||
ir_emit_comment(proc, str_lit("AssignStmt"));
|
||||
|
||||
|
||||
+67
-28
@@ -314,6 +314,11 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
|
||||
String foreign_name; \
|
||||
String link_name; \
|
||||
}) \
|
||||
AST_NODE_KIND(TypeDecl, "type declaration", struct { \
|
||||
Token token; \
|
||||
AstNode *name; \
|
||||
AstNode *type; \
|
||||
}) \
|
||||
AST_NODE_KIND(ImportDecl, "import declaration", struct { \
|
||||
Token token; \
|
||||
bool is_import; \
|
||||
@@ -1446,6 +1451,14 @@ AstNode *ast_proc_decl(AstFile *f, Token token, AstNode *name, AstNode *type, As
|
||||
return result;
|
||||
}
|
||||
|
||||
AstNode *ast_type_decl(AstFile *f, Token token, AstNode *name, AstNode *type) {
|
||||
AstNode *result = make_ast_node(f, AstNode_TypeDecl);
|
||||
result->TypeDecl.token = token;
|
||||
result->TypeDecl.name = name;
|
||||
result->TypeDecl.type = type;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AstNode *ast_import_decl(AstFile *f, Token token, bool is_import, Token relpath, Token import_name, AstNode *cond) {
|
||||
AstNode *result = make_ast_node(f, AstNode_ImportDecl);
|
||||
@@ -1590,6 +1603,11 @@ void fix_advance_to_next_stmt(AstFile *f) {
|
||||
case Token_Semicolon:
|
||||
return;
|
||||
|
||||
case Token_var:
|
||||
case Token_const:
|
||||
case Token_let:
|
||||
case Token_type:
|
||||
|
||||
case Token_if:
|
||||
case Token_when:
|
||||
case Token_return:
|
||||
@@ -1597,7 +1615,6 @@ void fix_advance_to_next_stmt(AstFile *f) {
|
||||
case Token_defer:
|
||||
case Token_asm:
|
||||
case Token_using:
|
||||
case Token_immutable:
|
||||
// case Token_thread_local:
|
||||
// case Token_no_alias:
|
||||
|
||||
@@ -1671,9 +1688,12 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
|
||||
return s->ProcLit.body != NULL;
|
||||
case AstNode_ProcDecl:
|
||||
return s->ProcDecl.body != NULL;
|
||||
case AstNode_TypeDecl:
|
||||
return is_semicolon_optional_for_node(f, s->TypeDecl.type);
|
||||
|
||||
|
||||
case AstNode_ValueDecl:
|
||||
if (s->ValueDecl.token.kind != Token_var) {
|
||||
if (s->ValueDecl.token.kind != Token_const) {
|
||||
if (s->ValueDecl.values.count > 0) {
|
||||
AstNode *last = s->ValueDecl.values[s->ValueDecl.values.count-1];
|
||||
return is_semicolon_optional_for_node(f, last);
|
||||
@@ -2511,7 +2531,7 @@ AstNode *parse_value_decl(AstFile *f, Token token) {
|
||||
Array<AstNode *> lhs = parse_lhs_expr_list(f);
|
||||
AstNode *type = NULL;
|
||||
Array<AstNode *> values = {};
|
||||
bool is_mutable = token.kind == Token_var;
|
||||
bool is_mutable = token.kind != Token_const;
|
||||
|
||||
if (allow_token(f, Token_Colon)) {
|
||||
type = parse_type(f);
|
||||
@@ -2551,12 +2571,14 @@ AstNode *parse_value_decl(AstFile *f, Token token) {
|
||||
values = make_ast_node_array(f);
|
||||
}
|
||||
|
||||
|
||||
Array<AstNode *> specs = {};
|
||||
array_init(&specs, heap_allocator(), 1);
|
||||
// Token token = ast_node_token(lhs[0]);
|
||||
// token.kind = is_mutable ? Token_var : Token_const;
|
||||
// token.string = is_mutable ? str_lit("var") : str_lit("const");
|
||||
return ast_value_decl(f, token, lhs, type, values);
|
||||
AstNode *decl = ast_value_decl(f, token, lhs, type, values);
|
||||
if (token.kind == Token_let) {
|
||||
decl->ValueDecl.flags |= VarDeclFlag_immutable;
|
||||
}
|
||||
return decl;
|
||||
}
|
||||
|
||||
AstNode *parse_proc_decl(AstFile *f) {
|
||||
@@ -2583,6 +2605,13 @@ AstNode *parse_proc_decl(AstFile *f) {
|
||||
return ast_proc_decl(f, token, name, type, body, tags, foreign_library, foreign_name, link_name);
|
||||
}
|
||||
|
||||
AstNode *parse_type_decl(AstFile *f) {
|
||||
Token token = expect_token(f, Token_type);
|
||||
AstNode *name = parse_ident(f);
|
||||
AstNode *type = parse_type(f);
|
||||
return ast_type_decl(f, token, name, type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) {
|
||||
@@ -2590,6 +2619,7 @@ AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) {
|
||||
switch (f->curr_token.kind) {
|
||||
case Token_var:
|
||||
case Token_const:
|
||||
case Token_let:
|
||||
next_token(f);
|
||||
return parse_value_decl(f, token);
|
||||
}
|
||||
@@ -2783,7 +2813,7 @@ FieldPrefixKind is_token_field_prefix(AstFile *f) {
|
||||
case Token_using:
|
||||
return FieldPrefix_Using;
|
||||
|
||||
case Token_immutable:
|
||||
case Token_let:
|
||||
return FieldPrefix_Immutable;
|
||||
|
||||
case Token_Hash: {
|
||||
@@ -3686,6 +3716,7 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
|
||||
case Token_var:
|
||||
case Token_const:
|
||||
case Token_let:
|
||||
s = parse_simple_stmt(f, StmtAllowFlag_None);
|
||||
expect_semicolon(f, s);
|
||||
return s;
|
||||
@@ -3695,6 +3726,11 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
expect_semicolon(f, s);
|
||||
return s;
|
||||
|
||||
case Token_type:
|
||||
s = parse_type_decl(f);
|
||||
expect_semicolon(f, s);
|
||||
return s;
|
||||
|
||||
|
||||
case Token_if: return parse_if_stmt(f);
|
||||
case Token_when: return parse_when_stmt(f);
|
||||
@@ -3722,27 +3758,30 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
case Token_using: {
|
||||
// TODO(bill): Make using statements better
|
||||
Token token = expect_token(f, Token_using);
|
||||
Array<AstNode *> list = parse_lhs_expr_list(f);
|
||||
if (list.count == 0) {
|
||||
syntax_error(token, "Illegal use of `using` statement");
|
||||
expect_semicolon(f, NULL);
|
||||
return ast_bad_stmt(f, token, f->curr_token);
|
||||
AstNode *decl = NULL;
|
||||
if (f->curr_token.kind == Token_var ||
|
||||
f->curr_token.kind == Token_let) {
|
||||
Token var = f->curr_token; next_token(f);
|
||||
decl = parse_value_decl(f, var);
|
||||
expect_semicolon(f, decl);
|
||||
} else {
|
||||
Array<AstNode *> list = parse_lhs_expr_list(f);
|
||||
if (list.count == 0) {
|
||||
syntax_error(token, "Illegal use of `using` statement");
|
||||
expect_semicolon(f, NULL);
|
||||
return ast_bad_stmt(f, token, f->curr_token);
|
||||
}
|
||||
|
||||
if (f->curr_token.kind != Token_Colon) {
|
||||
expect_semicolon(f, list[list.count-1]);
|
||||
return ast_using_stmt(f, token, list);
|
||||
}
|
||||
}
|
||||
|
||||
if (f->curr_token.kind != Token_Colon) {
|
||||
expect_semicolon(f, list[list.count-1]);
|
||||
return ast_using_stmt(f, token, list);
|
||||
}
|
||||
|
||||
Token var = ast_node_token(list[0]);
|
||||
var.kind = Token_var;
|
||||
var.string = str_lit("var");
|
||||
AstNode *decl = parse_value_decl(f, var);
|
||||
expect_semicolon(f, decl);
|
||||
|
||||
if (decl->kind == AstNode_ValueDecl) {
|
||||
if (decl != NULL && decl->kind == AstNode_ValueDecl) {
|
||||
#if 1
|
||||
if (decl->ValueDecl.token.kind != Token_var) {
|
||||
if (decl->ValueDecl.token.kind == Token_const) {
|
||||
syntax_error(token, "`using` may not be applied to constant declarations");
|
||||
return decl;
|
||||
}
|
||||
@@ -3761,13 +3800,13 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
return ast_bad_stmt(f, token, f->curr_token);
|
||||
} break;
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
case Token_immutable: {
|
||||
Token token = expect_token(f, Token_immutable);
|
||||
AstNode *node = parse_stmt(f);
|
||||
|
||||
if (node->kind == AstNode_ValueDecl) {
|
||||
if (node->ValueDecl.token.kind != Token_var) {
|
||||
if (node->ValueDecl.token.kind == Token_const) {
|
||||
syntax_error(token, "`immutable` may not be applied to constant declarations");
|
||||
} else {
|
||||
node->ValueDecl.flags |= VarDeclFlag_immutable;
|
||||
@@ -3939,7 +3978,7 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
AstNode *s = parse_stmt(f);
|
||||
|
||||
if (s->kind == AstNode_ValueDecl) {
|
||||
if (s->ValueDecl.token.kind != Token_var) {
|
||||
if (s->ValueDecl.token.kind == Token_const) {
|
||||
syntax_error(token, "`thread_local` may not be applied to constant declarations");
|
||||
}
|
||||
if (f->curr_proc != NULL) {
|
||||
|
||||
+1
-1
@@ -1969,7 +1969,7 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(vd, ValueDecl, node);
|
||||
if (vd->token.kind == Token_var) {
|
||||
if (vd->token.kind != Token_const) {
|
||||
ssaModule *m = p->module;
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
|
||||
if (vd->values.count == 0) {
|
||||
|
||||
+1
-1
@@ -83,6 +83,7 @@ TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
|
||||
\
|
||||
TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
||||
TOKEN_KIND(Token_var, "var"), \
|
||||
TOKEN_KIND(Token_let, "let"), \
|
||||
TOKEN_KIND(Token_const, "const"), \
|
||||
TOKEN_KIND(Token_type, "type"), \
|
||||
TOKEN_KIND(Token_when, "when"), \
|
||||
@@ -109,7 +110,6 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
||||
TOKEN_KIND(Token_dynamic, "dynamic"), \
|
||||
TOKEN_KIND(Token_map, "map"), \
|
||||
TOKEN_KIND(Token_using, "using"), \
|
||||
TOKEN_KIND(Token_immutable, "immutable"), \
|
||||
TOKEN_KIND(Token_context, "context"), \
|
||||
TOKEN_KIND(Token_push_context, "push_context"), \
|
||||
TOKEN_KIND(Token_push_allocator, "push_allocator"), \
|
||||
|
||||
Reference in New Issue
Block a user