when statement; Better entity collection system (for both local and global); Better parsing for record declarations

This commit is contained in:
Ginger Bill
2016-11-29 23:57:06 +00:00
parent b232b9d5ea
commit d9c686b53d
9 changed files with 309 additions and 265 deletions
+9 -20
View File
@@ -1,29 +1,18 @@
// #import "fmt.odin"
#import "fmt.odin"
#import "utf8.odin"
when ODIN_OS == "window" {
when ODIN_OS != "window" {
} else {
MAX :: 64
}
#import "fmt.odin"
} else {
}
main :: proc() {
when true {
OffsetType :: type int
}
// MAX :: 64
buf: [MAX]rune
backing: [MAX]byte
offset: OffsetType
offset: int
when MAX > 0 {
msg := "Hello"
}
MAX :: 64
msg := "Hello"
count := utf8.rune_count(msg)
assert(count <= MAX)
runes := buf[:count]
@@ -33,14 +22,14 @@ main :: proc() {
s := msg[offset:]
r, len := utf8.decode_rune(s)
runes[count-i-1] = r
offset += len as OffsetType
offset += len
}
offset = 0
for i := 0; i < count; i++ {
data, len := utf8.encode_rune(runes[i])
copy(backing[offset:], data[:len])
offset += len as OffsetType
offset += len
}
reverse := backing[:offset] as string
+3 -1
View File
@@ -1,4 +1,6 @@
#foreign_system_library "opengl32"
when ODIN_OS == "windows" {
#foreign_system_library "opengl32"
}
#import "win32.odin"
#load "opengl_constants.odin"
+3 -1
View File
@@ -1,4 +1,6 @@
#import "win32.odin"
when ODIN_OS == "windows" {
#import "win32.odin"
}
#import "fmt.odin"
File_Time :: type u64
+4 -4
View File
@@ -1,7 +1,7 @@
#foreign_system_library "user32"
#foreign_system_library "gdi32"
_:= compile_assert(ODIN_OS == "windows")
when ODIN_OS == "windows" {
#foreign_system_library "user32"
#foreign_system_library "gdi32"
}
HANDLE :: type rawptr
HWND :: type HANDLE
+23 -16
View File
@@ -917,10 +917,12 @@ Type *const curr_procedure(Checker *c) {
}
void add_curr_ast_file(Checker *c, AstFile *file) {
TokenPos zero_pos = {0};
global_error_collector.prev = zero_pos;
c->curr_ast_file = file;
c->context.decl = file->decl_info;
if (file != NULL) {
TokenPos zero_pos = {0};
global_error_collector.prev = zero_pos;
c->curr_ast_file = file;
c->context.decl = file->decl_info;
}
}
@@ -966,9 +968,6 @@ MapEntity generate_minimum_dependency_map(CheckerInfo *info, Entity *start) {
return map;
}
void check_collect_entities(Checker *c, Scope *parent_scope, AstNodeArray nodes, MapScope *file_scopes);
#include "expr.c"
#include "decl.c"
@@ -1072,6 +1071,7 @@ void check_global_entities_by_kind(Checker *c, EntityKind kind) {
}
}
void check_global_collect_entities(Checker *c, Scope *parent_scope, AstNodeArray nodes, MapScope *file_scopes);
void check_global_when_stmt(Checker *c, Scope *parent_scope, AstNodeWhenStmt *ws, MapScope *file_scopes) {
Operand operand = {Addressing_Invalid};
@@ -1088,11 +1088,11 @@ void check_global_when_stmt(Checker *c, Scope *parent_scope, AstNodeWhenStmt *ws
if (operand.value.kind == ExactValue_Bool &&
operand.value.value_bool == true) {
ast_node(body, BlockStmt, ws->body);
check_collect_entities(c, parent_scope, body->stmts, file_scopes);
check_global_collect_entities(c, parent_scope, body->stmts, file_scopes);
} else if (ws->else_stmt) {
switch (ws->else_stmt->kind) {
case AstNode_BlockStmt:
check_collect_entities(c, parent_scope, ws->else_stmt->BlockStmt.stmts, file_scopes);
check_global_collect_entities(c, parent_scope, ws->else_stmt->BlockStmt.stmts, file_scopes);
break;
case AstNode_WhenStmt:
check_global_when_stmt(c, parent_scope, &ws->else_stmt->WhenStmt, file_scopes);
@@ -1104,7 +1104,7 @@ void check_global_when_stmt(Checker *c, Scope *parent_scope, AstNodeWhenStmt *ws
}
}
}
void check_collect_entities(Checker *c, Scope *parent_scope, AstNodeArray nodes, MapScope *file_scopes) {
void check_global_collect_entities(Checker *c, Scope *parent_scope, AstNodeArray nodes, MapScope *file_scopes) {
for_array(decl_index, nodes) {
AstNode *decl = nodes.e[decl_index];
if (!is_ast_node_decl(decl) && !is_ast_node_when_stmt(decl)) {
@@ -1242,9 +1242,8 @@ void check_collect_entities(Checker *c, Scope *parent_scope, AstNodeArray nodes,
try_add_foreign_library_path(c, file_str);
case_end;
case_ast_node(ws, WhenStmt, decl);
check_global_when_stmt(c, parent_scope, ws, file_scopes);
// Will be handled later
case_end;
case_ast_node(cd, ConstDecl, decl);
for_array(i, cd->values) {
AstNode *name = cd->names.e[i];
@@ -1267,7 +1266,6 @@ void check_collect_entities(Checker *c, Scope *parent_scope, AstNodeArray nodes,
error(ast_node_token(decl), "Extra initial expression");
}
case_end;
case_ast_node(vd, VarDecl, decl);
if (!parent_scope->is_file) {
// NOTE(bill): Within a procedure, variables must be in order
@@ -1308,7 +1306,6 @@ void check_collect_entities(Checker *c, Scope *parent_scope, AstNodeArray nodes,
add_entity_and_decl_info(c, name, e, d);
}
case_end;
case_ast_node(td, TypeDecl, decl);
ast_node(n, Ident, td->name);
Entity *e = make_entity_type_name(c->allocator, parent_scope, *n, NULL);
@@ -1317,7 +1314,6 @@ void check_collect_entities(Checker *c, Scope *parent_scope, AstNodeArray nodes,
d->type_expr = td->type;
add_entity_and_decl_info(c, td->name, e, d);
case_end;
case_ast_node(pd, ProcDecl, decl);
ast_node(n, Ident, pd->name);
Token token = *n;
@@ -1335,6 +1331,17 @@ void check_collect_entities(Checker *c, Scope *parent_scope, AstNodeArray nodes,
break;
}
}
// NOTE(bill): `when` stmts need to be handled after the other as the condition may refer to something
// declared after this stmt in source
for_array(decl_index, nodes) {
AstNode *decl = nodes.e[decl_index];
switch (decl->kind) {
case_ast_node(ws, WhenStmt, decl);
check_global_when_stmt(c, parent_scope, ws, file_scopes);
case_end;
}
}
}
@@ -1371,7 +1378,7 @@ void check_parsed_files(Checker *c) {
for_array(i, c->parser->files) {
AstFile *f = &c->parser->files.e[i];
add_curr_ast_file(c, f);
check_collect_entities(c, f->scope, f->decls, &file_scopes);
check_global_collect_entities(c, f->scope, f->decls, &file_scopes);
}
check_global_entities_by_kind(c, Entity_TypeName);
+205 -89
View File
@@ -20,6 +20,206 @@ gb_inline Type *check_type(Checker *c, AstNode *expression) {
typedef struct DelayedEntity {
Entity *entity;
DeclInfo *decl;
} DelayedEntity;
typedef struct DelayedOtherFields {
Entity **other_fields;
isize other_field_count;
isize other_field_index;
MapEntity *entity_map;
} DelayedOtherFields;
typedef Array(DelayedEntity) DelayedEntities;
void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntities *delayed_entities, DelayedOtherFields *dof);
void check_local_collect_entities_from_when_stmt(Checker *c, AstNodeWhenStmt *ws, DelayedEntities *delayed_entities, DelayedOtherFields *dof) {
Operand operand = {Addressing_Invalid};
check_expr(c, &operand, ws->cond);
if (operand.mode != Addressing_Invalid && !is_type_boolean(operand.type)) {
error(ast_node_token(ws->cond), "Non-boolean condition in `when` statement");
}
if (operand.mode != Addressing_Constant) {
error(ast_node_token(ws->cond), "Non-constant condition in `when` statement");
}
if (ws->body == NULL || ws->body->kind != AstNode_BlockStmt) {
error(ast_node_token(ws->cond), "Invalid body for `when` statement");
} else {
if (operand.value.kind == ExactValue_Bool &&
operand.value.value_bool) {
check_local_collect_entities(c, ws->body->BlockStmt.stmts, delayed_entities, dof);
} else if (ws->else_stmt) {
switch (ws->else_stmt->kind) {
case AstNode_BlockStmt:
check_local_collect_entities(c, ws->else_stmt->BlockStmt.stmts, delayed_entities, dof);
break;
case AstNode_WhenStmt:
check_local_collect_entities_from_when_stmt(c, &ws->else_stmt->WhenStmt, delayed_entities, dof);
break;
default:
error(ast_node_token(ws->else_stmt), "Invalid `else` statement in `when` statement");
break;
}
}
}
}
// NOTE(bill): The `dof` is for use within records
void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntities *delayed_entities, DelayedOtherFields *dof) {
for_array(i, nodes) {
AstNode *node = nodes.e[i];
switch (node->kind) {
case_ast_node(ws, WhenStmt, node);
// Will be handled later
case_end;
case_ast_node(cd, ConstDecl, node);
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
isize entity_count = cd->names.count;
isize entity_index = 0;
Entity **entities = gb_alloc_array(c->tmp_allocator, Entity *, entity_count);
for_array(i, cd->values) {
AstNode *name = cd->names.e[i];
AstNode *value = cd->values.e[i];
ExactValue v = {ExactValue_Invalid};
Entity *e = make_entity_constant(c->allocator, c->context.scope, name->Ident, NULL, v);
e->identifier = name;
entities[entity_index++] = e;
DeclInfo *d = make_declaration_info(c->allocator, e->scope);
d->type_expr = cd->type;
d->init_expr = value;
add_entity_and_decl_info(c, name, e, d);
DelayedEntity delay = {e, d};
array_add(delayed_entities, delay);
}
isize lhs_count = cd->names.count;
isize rhs_count = cd->values.count;
// TODO(bill): Better error messages or is this good enough?
if (rhs_count == 0 && cd->type == NULL) {
error(ast_node_token(node), "Missing type or initial expression");
} else if (lhs_count < rhs_count) {
error(ast_node_token(node), "Extra initial expression");
}
if (dof != NULL) {
// NOTE(bill): Within a record
for_array(i, cd->names) {
AstNode *name = cd->names.e[i];
Entity *e = entities[i];
Token name_token = name->Ident;
if (str_eq(name_token.string, str_lit("_"))) {
dof->other_fields[dof->other_field_index++] = e;
} else {
HashKey key = hash_string(name_token.string);
if (map_entity_get(dof->entity_map, key) != NULL) {
// TODO(bill): Scope checking already checks the declaration
error(name_token, "`%.*s` is already declared in this record", LIT(name_token.string));
} else {
map_entity_set(dof->entity_map, key, e);
dof->other_fields[dof->other_field_index++] = e;
}
add_entity(c, c->context.scope, name, e);
}
}
}
gb_temp_arena_memory_end(tmp);
case_end;
case_ast_node(pd, ProcDecl, node);
// NOTE(bill): This must be handled here so it has access to the parent scope stuff
// e.g. using
Entity *e = make_entity_procedure(c->allocator, c->context.scope, pd->name->Ident, NULL);
e->identifier = pd->name;
DeclInfo *d = make_declaration_info(c->allocator, e->scope);
d->proc_decl = node;
add_entity_and_decl_info(c, pd->name, e, d);
check_entity_decl(c, e, d, NULL, NULL);
case_end;
case_ast_node(td, TypeDecl, node);
Token name_token = td->name->Ident;
Entity *e = make_entity_type_name(c->allocator, c->context.scope, name_token, NULL);
e->identifier = td->name;
DeclInfo *d = make_declaration_info(c->allocator, e->scope);
d->type_expr = td->type;
add_entity_and_decl_info(c, td->name, e, d);
DelayedEntity delay = {e, d};
array_add(delayed_entities, delay);
if (dof != NULL) {
if (str_eq(name_token.string, str_lit("_"))) {
dof->other_fields[dof->other_field_index++] = e;
} else {
HashKey key = hash_string(name_token.string);
if (map_entity_get(dof->entity_map, key) != NULL) {
// TODO(bill): Scope checking already checks the declaration
error(name_token, "`%.*s` is already declared in this record", LIT(name_token.string));
} else {
map_entity_set(dof->entity_map, key, e);
dof->other_fields[dof->other_field_index++] = e;
}
add_entity(c, c->context.scope, td->name, e);
add_entity_use(c, td->name, e);
}
}
case_end;
}
}
// NOTE(bill): `when` stmts need to be handled after the other as the condition may refer to something
// declared after this stmt in source
for_array(i, nodes) {
AstNode *node = nodes.e[i];
switch (node->kind) {
case_ast_node(ws, WhenStmt, node);
check_local_collect_entities_from_when_stmt(c, ws, delayed_entities, dof);
case_end;
}
}
}
void check_scope_decls(Checker *c, AstNodeArray nodes, isize reserve_size, DelayedOtherFields *dof) {
DelayedEntities delayed_entities;
array_init_reserve(&delayed_entities, heap_allocator(), reserve_size);
check_local_collect_entities(c, nodes, &delayed_entities, dof);
for_array(i, delayed_entities) {
DelayedEntity delayed = delayed_entities.e[i];
if (delayed.entity->kind == Entity_TypeName) {
check_entity_decl(c, delayed.entity, delayed.decl, NULL, NULL);
}
}
for_array(i, delayed_entities) {
DelayedEntity delayed = delayed_entities.e[i];
if (delayed.entity->kind == Entity_Constant) {
check_entity_decl(c, delayed.entity, delayed.decl, NULL, NULL);
}
}
array_free(&delayed_entities);
}
bool check_is_assignable_to_using_subtype(Type *dst, Type *src) {
Type *prev_src = src;
// Type *prev_dst = dst;
@@ -247,96 +447,12 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
isize other_field_index = 0;
Entity *using_index_expr = NULL;
DelayedOtherFields dof = {0};
dof.other_fields = other_fields;
dof.other_field_count = other_field_count;
dof.entity_map = &entity_map;
typedef struct {
Entity *e;
AstNode *t;
} Delay;
Array(Delay) delayed_const; array_init_reserve(&delayed_const, c->tmp_allocator, other_field_count);
Array(Delay) delayed_type; array_init_reserve(&delayed_type, c->tmp_allocator, other_field_count);
for_array(decl_index, decls) {
AstNode *decl = decls.e[decl_index];
if (decl->kind == AstNode_ConstDecl) {
ast_node(cd, ConstDecl, decl);
isize entity_count = cd->names.count;
isize entity_index = 0;
Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
for_array(i, cd->values) {
AstNode *name = cd->names.e[i];
AstNode *value = cd->values.e[i];
GB_ASSERT(name->kind == AstNode_Ident);
ExactValue v = {ExactValue_Invalid};
Token name_token = name->Ident;
Entity *e = make_entity_constant(c->allocator, c->context.scope, name_token, NULL, v);
entities[entity_index++] = e;
Delay delay = {e, cd->type};
array_add(&delayed_const, delay);
}
isize lhs_count = cd->names.count;
isize rhs_count = cd->values.count;
// TODO(bill): Better error messages or is this good enough?
if (rhs_count == 0 && cd->type == NULL) {
error(ast_node_token(node), "Missing type or initial expression");
} else if (lhs_count < rhs_count) {
error(ast_node_token(node), "Extra initial expression");
}
for_array(i, cd->names) {
AstNode *name = cd->names.e[i];
Entity *e = entities[i];
Token name_token = name->Ident;
if (str_eq(name_token.string, str_lit("_"))) {
other_fields[other_field_index++] = e;
} else {
HashKey key = hash_string(name_token.string);
if (map_entity_get(&entity_map, key) != NULL) {
// TODO(bill): Scope checking already checks the declaration
error(name_token, "`%.*s` is already declared in this structure", LIT(name_token.string));
} else {
map_entity_set(&entity_map, key, e);
other_fields[other_field_index++] = e;
}
add_entity(c, c->context.scope, name, e);
}
}
} else if (decl->kind == AstNode_TypeDecl) {
ast_node(td, TypeDecl, decl);
Token name_token = td->name->Ident;
Entity *e = make_entity_type_name(c->allocator, c->context.scope, name_token, NULL);
Delay delay = {e, td->type};
array_add(&delayed_type, delay);
if (str_eq(name_token.string, str_lit("_"))) {
other_fields[other_field_index++] = e;
} else {
HashKey key = hash_string(name_token.string);
if (map_entity_get(&entity_map, key) != NULL) {
// TODO(bill): Scope checking already checks the declaration
error(name_token, "`%.*s` is already declared in this structure", LIT(name_token.string));
} else {
map_entity_set(&entity_map, key, e);
other_fields[other_field_index++] = e;
}
add_entity(c, c->context.scope, td->name, e);
add_entity_use(c, td->name, e);
}
}
}
for_array(i, delayed_type) {
check_const_decl(c, delayed_type.e[i].e, delayed_type.e[i].t, NULL);
}
for_array(i, delayed_const) {
check_type_decl(c, delayed_const.e[i].e, delayed_const.e[i].t, NULL, NULL);
}
check_scope_decls(c, decls, 1.2*other_field_count, &dof);
if (node->kind == AstNode_UnionType) {
isize field_index = 0;
+4 -64
View File
@@ -11,74 +11,12 @@ typedef enum StmtFlag {
} StmtFlag;
void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
if (stmts.count == 0) {
return;
}
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
typedef struct {
Entity *e;
DeclInfo *d;
} Delay;
Array(Delay) delayed_const; array_init_reserve(&delayed_const, c->tmp_allocator, stmts.count);
Array(Delay) delayed_type; array_init_reserve(&delayed_type, c->tmp_allocator, stmts.count);
for_array(i, stmts) {
AstNode *node = stmts.e[i];
switch (node->kind) {
case_ast_node(cd, ConstDecl, node);
for_array(i, cd->values) {
AstNode *name = cd->names.e[i];
AstNode *value = cd->values.e[i];
ExactValue v = {ExactValue_Invalid};
Entity *e = make_entity_constant(c->allocator, c->context.scope, name->Ident, NULL, v);
e->identifier = name;
DeclInfo *d = make_declaration_info(c->allocator, e->scope);
d->type_expr = cd->type;
d->init_expr = value;
add_entity_and_decl_info(c, name, e, d);
Delay delay = {e, d};
array_add(&delayed_const, delay);
}
isize lhs_count = cd->names.count;
isize rhs_count = cd->values.count;
if (rhs_count == 0 && cd->type == NULL) {
error(ast_node_token(node), "Missing type or initial expression");
} else if (lhs_count < rhs_count) {
error(ast_node_token(node), "Extra initial expression");
}
case_end;
case_ast_node(td, TypeDecl, node);
Entity *e = make_entity_type_name(c->allocator, c->context.scope, td->name->Ident, NULL);
e->identifier = td->name;
DeclInfo *d = make_declaration_info(c->allocator, e->scope);
d->type_expr = td->type;
add_entity_and_decl_info(c, td->name, e, d);
Delay delay = {e, d};
array_add(&delayed_type, delay);
case_end;
}
}
for_array(i, delayed_type) {
check_entity_decl(c, delayed_type.e[i].e, delayed_type.e[i].d, NULL, NULL);
}
for_array(i, delayed_const) {
check_entity_decl(c, delayed_const.e[i].e, delayed_const.e[i].d, NULL, NULL);
}
check_scope_decls(c, stmts, 1.2*stmts.count, NULL);
bool ft_ok = (flags & Stmt_FallthroughAllowed) != 0;
u32 f = flags & (~Stmt_FallthroughAllowed);
@@ -95,7 +33,6 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
check_stmt(c, n, new_flags);
}
gb_temp_arena_memory_end(tmp);
}
bool check_is_terminating_list(AstNodeArray stmts) {
@@ -1147,6 +1084,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
case_end;
case_ast_node(pd, ProcDecl, node);
// NOTE(bill): Handled elsewhere
#if 0
// NOTE(bill): This must be handled here so it has access to the parent scope stuff
// e.g. using
Entity *e = make_entity_procedure(c->allocator, c->context.scope, pd->name->Ident, NULL);
@@ -1157,6 +1096,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
add_entity_and_decl_info(c, pd->name, e, d);
check_entity_decl(c, e, d, NULL, NULL);
#endif
case_end;
}
}
+1 -16
View File
@@ -667,24 +667,9 @@ bool is_type_comparable(Type *t) {
t = base_type(get_enum_base_type(t));
switch (t->kind) {
case Type_Basic:
return t->kind != Basic_UntypedNil;
return t->kind != Basic_UntypedNil && t->kind != Basic_any;
case Type_Pointer:
return true;
case Type_Record: {
if (false && is_type_struct(t)) {
// TODO(bill): Should I even allow this?
for (isize i = 0; i < t->Record.field_count; i++) {
if (!is_type_comparable(t->Record.fields[i]->type))
return false;
}
} else if (is_type_enum(t)) {
return is_type_comparable(t->Record.enum_base);
}
return false;
} break;
case Type_Array:
return false;
// return is_type_comparable(t->Array.elem);
case Type_Vector:
return is_type_comparable(t->Vector.elem);
case Type_Proc:
+57 -54
View File
@@ -1086,6 +1086,7 @@ void fix_advance_to_next_stmt(AstFile *f) {
return;
case Token_if:
case Token_when:
case Token_return:
case Token_for:
case Token_match:
@@ -1966,55 +1967,61 @@ AstNodeArray parse_parameter_list(AstFile *f) {
}
AstNodeArray parse_struct_params(AstFile *f, isize *decl_count_, bool using_allowed) {
AstNodeArray parse_record_params(AstFile *f, isize *decl_count_, bool using_allowed, String context) {
AstNodeArray decls = make_ast_node_array(f);
isize decl_count = 0;
while (f->curr_token.kind == Token_Identifier ||
f->curr_token.kind == Token_using) {
bool is_using = false;
if (allow_token(f, Token_using)) {
is_using = true;
}
AstNodeArray names = parse_lhs_expr_list(f);
if (names.count == 0) {
syntax_error(f->curr_token, "Empty field declaration");
}
while (f->curr_token.kind != Token_CloseBrace &&
f->curr_token.kind != Token_EOF) {
AstNode *decl = parse_stmt(f);
if (is_ast_node_decl(decl) ||
decl->kind == AstNode_UsingStmt ||
decl->kind == AstNode_EmptyStmt) {
switch (decl->kind) {
case AstNode_EmptyStmt:
break;
if (!using_allowed && is_using) {
syntax_error(f->curr_token, "Cannot apply `using` to members of a union");
is_using = false;
}
if (names.count > 1 && is_using) {
syntax_error(f->curr_token, "Cannot apply `using` to more than one of the same type");
}
case AstNode_ProcDecl:
syntax_error(f->curr_token, "Procedure declarations are not allowed within a %.*s", LIT(context));
break;
AstNode *decl = NULL;
case AstNode_UsingStmt: {
bool is_using = true;
if (!using_allowed) {
syntax_error(f->curr_token, "Cannot apply `using` to members of a %.*s", LIT(context));
is_using = false;
}
if (decl->UsingStmt.node->kind == AstNode_VarDecl) {
AstNode *vd = decl->UsingStmt.node;
vd->VarDecl.is_using = is_using && using_allowed;
if (vd->VarDecl.values.count > 0) {
syntax_error(f->curr_token, "Default variable assignments within a %.*s will be ignored", LIT(context));
}
array_add(&decls, vd);
} else {
syntax_error(ast_node_token(decl), "Illegal %.*s field", LIT(context));
}
} break;
if (f->curr_token.kind == Token_Colon) {
decl = parse_decl(f, names);
case AstNode_VarDecl: {
if (decl->VarDecl.values.count > 0) {
syntax_error(f->curr_token, "Default variable assignments within a %.*s will be ignored", LIT(context));
}
array_add(&decls, decl);
}
if (decl->kind == AstNode_ProcDecl) {
syntax_error(f->curr_token, "Procedure declarations are not allowed within a structure");
decl = make_bad_decl(f, ast_node_token(names.e[0]), f->curr_token);
case AstNode_BadDecl:
break;
case AstNode_ConstDecl:
case AstNode_TypeDecl:
default:
decl_count += 1;
array_add(&decls, decl);
break;
}
} else {
syntax_error(f->curr_token, "Illegal structure field");
decl = make_bad_decl(f, ast_node_token(names.e[0]), f->curr_token);
}
expect_semicolon_after_stmt(f, decl);
if (is_ast_node_decl(decl)) {
array_add(&decls, decl);
if (decl->kind == AstNode_VarDecl) {
decl->VarDecl.is_using = is_using && using_allowed;
if (decl->VarDecl.values.count > 0) {
syntax_error(f->curr_token, "Default variable assignments within a structure will be ignored (at the moment)");
}
} else {
decl_count += 1;
}
syntax_error(ast_node_token(decl), "Illegal record field: %.*s", LIT(ast_node_strings[decl->kind]));
}
}
@@ -2063,7 +2070,11 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
next_token(f);
} else if (f->curr_token.kind == Token_vector) {
next_token(f);
count_expr = parse_expr(f, false);
if (f->curr_token.kind != Token_CloseBracket) {
count_expr = parse_expr(f, false);
} else {
syntax_error(f->curr_token, "Vector type missing count");
}
is_vector = true;
} else if (f->curr_token.kind != Token_CloseBracket) {
count_expr = parse_expr(f, false);
@@ -2076,15 +2087,6 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
return make_array_type(f, token, count_expr, parse_type(f));
}
// case Token_OpenBrace: {
// f->expr_level++;
// Token token = expect_token(f, Token_OpenBrace);
// AstNode *count_expr = parse_expr(f, false);
// expect_token(f, Token_CloseBrace);
// f->expr_level--;
// return make_vector_type(f, token, count_expr, parse_type(f));
// }
case Token_struct: {
Token token = expect_token(f, Token_struct);
bool is_packed = false;
@@ -2112,7 +2114,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
Token open = expect_token_after(f, Token_OpenBrace, "`struct`");
isize decl_count = 0;
AstNodeArray decls = parse_struct_params(f, &decl_count, true);
AstNodeArray decls = parse_record_params(f, &decl_count, true, str_lit("struct"));
Token close = expect_token(f, Token_CloseBrace);
return make_struct_type(f, token, decls, decl_count, is_packed, is_ordered);
@@ -2122,7 +2124,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
Token token = expect_token(f, Token_union);
Token open = expect_token_after(f, Token_OpenBrace, "`union`");
isize decl_count = 0;
AstNodeArray decls = parse_struct_params(f, &decl_count, false);
AstNodeArray decls = parse_record_params(f, &decl_count, false, str_lit("union"));
Token close = expect_token(f, Token_CloseBrace);
return make_union_type(f, token, decls, decl_count);
@@ -2132,7 +2134,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
Token token = expect_token(f, Token_raw_union);
Token open = expect_token_after(f, Token_OpenBrace, "`raw_union`");
isize decl_count = 0;
AstNodeArray decls = parse_struct_params(f, &decl_count, true);
AstNodeArray decls = parse_record_params(f, &decl_count, true, str_lit("raw_union"));
Token close = expect_token(f, Token_CloseBrace);
return make_raw_union_type(f, token, decls, decl_count);
@@ -2192,8 +2194,9 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
break;
case Token_Eq:
if (f->prev_token.kind == Token_Colon)
if (f->prev_token.kind == Token_Colon) {
break;
}
// fallthrough
default:
syntax_error(f->curr_token,