alias and unified parameters lists for procedures and structures.

This commit is contained in:
gingerBill
2016-07-25 11:14:25 +01:00
parent 9d8355d361
commit 32ab8fcf99
10 changed files with 217 additions and 103 deletions
+6
View File
@@ -0,0 +1,6 @@
type Vec2: struct { x, y: f32 }
main :: proc() {
}
+14 -6
View File
@@ -297,12 +297,12 @@ void init_universal_scope(void) {
for (isize i = 0; i < gb_count_of(basic_types); i++) {
Token token = {Token_Identifier};
token.string = basic_types[i].basic.name;
add_global_entity(alloc_entity(a, Entity_TypeName, NULL, token, &basic_types[i]));
add_global_entity(make_entity_type_name(a, NULL, token, &basic_types[i]));
}
for (isize i = 0; i < gb_count_of(basic_type_aliases); i++) {
Token token = {Token_Identifier};
token.string = basic_type_aliases[i].basic.name;
add_global_entity(alloc_entity(a, Entity_TypeName, NULL, token, &basic_type_aliases[i]));
add_global_entity(make_entity_type_name(a, NULL, token, &basic_type_aliases[i]));
}
// Constants
@@ -555,8 +555,8 @@ void check_parsed_files(Checker *c) {
add_file_entity(c, name, e, di);
}
isize lhs_count = vd->name_list_count;
isize rhs_count = vd->value_list_count;
isize lhs_count = vd->name_count;
isize rhs_count = vd->value_count;
if (rhs_count == 0 && vd->type_expression == NULL) {
error(&c->error_collector, ast_node_token(decl), "Missing type or initial expression");
@@ -566,11 +566,11 @@ void check_parsed_files(Checker *c) {
} break;
case Declaration_Mutable: {
isize entity_count = vd->name_list_count;
isize entity_count = vd->name_count;
isize entity_index = 0;
Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
DeclarationInfo *di = NULL;
if (vd->value_list_count == 1) {
if (vd->value_count == 1) {
di = make_declaration_info(gb_heap_allocator(), c->global_scope);
di->entities = entities;
di->entity_count = entity_count;
@@ -610,6 +610,14 @@ void check_parsed_files(Checker *c) {
add_file_entity(c, identifier, e, d);
} break;
case AstNode_AliasDeclaration: {
AstNode *identifier = decl->alias_declaration.name;
Entity *e = make_entity_alias_name(c->allocator, c->global_scope, identifier->identifier.token, NULL);
DeclarationInfo *d = make_declaration_info(c->allocator, e->parent);
d->type_expr = decl->alias_declaration.type_expression;
add_file_entity(c, identifier, e, d);
} break;
case AstNode_ProcedureDeclaration: {
AstNode *identifier = decl->procedure_declaration.name;
Token token = identifier->identifier.token;
+9 -2
View File
@@ -8,6 +8,7 @@ enum EntityKind {
Entity_Constant,
Entity_Variable,
Entity_TypeName,
Entity_AliasName,
Entity_Procedure,
Entity_Builtin,
@@ -33,6 +34,7 @@ struct Entity {
b8 used;
} variable;
struct {} type_name;
struct {} alias_name;
struct {} procedure;
struct { BuiltinProcedureId id; } builtin;
};
@@ -70,14 +72,19 @@ Entity *make_entity_type_name(gbAllocator a, Scope *parent, Token token, Type *t
return entity;
}
Entity *make_entity_alias_name(gbAllocator a, Scope *parent, Token token, Type *type) {
Entity *entity = alloc_entity(a, Entity_AliasName, parent, token, type);
return entity;
}
Entity *make_entity_param(gbAllocator a, Scope *parent, Token token, Type *type) {
Entity *entity = alloc_entity(a, Entity_Variable, parent, token, type);
Entity *entity = make_entity_variable(a, parent, token, type);
entity->variable.used = true;
return entity;
}
Entity *make_entity_field(gbAllocator a, Scope *parent, Token token, Type *type) {
Entity *entity = alloc_entity(a, Entity_Variable, parent, token, type);
Entity *entity = make_entity_variable(a, parent, token, type);
entity->variable.is_field = true;
return entity;
}
+9 -9
View File
@@ -123,13 +123,13 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
// gb_printf("%td -> %td\n", param_count, result_count);
Type *params = check_get_params(c, c->context.scope, proc_type_node->procedure_type.param_list, param_count);
Type *results = check_get_results(c, c->context.scope, proc_type_node->procedure_type.results_list, result_count);
Type *results = check_get_results(c, c->context.scope, proc_type_node->procedure_type.result_list, result_count);
type->procedure.scope = c->context.scope;
type->procedure.params = params;
type->procedure.params_count = proc_type_node->procedure_type.param_count;
type->procedure.results = results;
type->procedure.results_count = proc_type_node->procedure_type.result_count;
type->procedure.scope = c->context.scope;
type->procedure.params = params;
type->procedure.param_count = proc_type_node->procedure_type.param_count;
type->procedure.results = results;
type->procedure.result_count = proc_type_node->procedure_type.result_count;
}
@@ -171,6 +171,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) {
break;
case Entity_TypeName:
case Entity_AliasName:
o->mode = Addressing_Type;
break;
@@ -1416,9 +1417,9 @@ ExpressionKind check_call_expression(Checker *c, Operand *operand, AstNode *call
check_call_arguments(c, operand, proc_type, call);
auto *proc = &proc_type->procedure;
if (proc->results_count == 0) {
if (proc->result_count == 0) {
operand->mode = Addressing_NoValue;
} else if (proc->results_count == 1) {
} else if (proc->result_count == 1) {
operand->mode = Addressing_Value;
operand->type = proc->results->tuple.variables[0]->type;
} else {
@@ -1524,7 +1525,6 @@ void check_expression_with_type_hint(Checker *c, Operand *o, AstNode *e, Type *t
}
}
ExpressionKind check__expression_base(Checker *c, Operand *o, AstNode *node, Type *type_hint) {
ExpressionKind kind = Expression_Statement;
+27 -5
View File
@@ -360,6 +360,17 @@ void check_type_declaration(Checker *c, Entity *e, AstNode *type_expr, Type *nam
set_base_type(named, get_base_type(get_base_type(named)));
}
void check_alias_declaration(Checker *c, Entity *e, AstNode *type_expr, Type *alias_type) {
GB_ASSERT(e->type == NULL);
Type *named = make_type_alias(c->allocator, e->token.string, NULL, e);
named->alias.alias_name = e;
set_base_type(alias_type, named);
e->type = named;
check_type(c, type_expr, named);
set_base_type(named, get_base_type(get_base_type(named)));
}
void check_procedure_body(Checker *c, Token token, DeclarationInfo *decl, Type *type, AstNode *body) {
GB_ASSERT(body->kind == AstNode_BlockStatement);
@@ -370,7 +381,7 @@ void check_procedure_body(Checker *c, Token token, DeclarationInfo *decl, Type *
push_procedure(c, type);
check_statement_list(c, body->block_statement.list, 0);
if (type->procedure.results_count > 0) {
if (type->procedure.result_count > 0) {
if (!check_is_terminating(c, body)) {
error(&c->error_collector, body->block_statement.close, "Missing return statement at the end of the procedure");
}
@@ -498,6 +509,9 @@ void check_entity_declaration(Checker *c, Entity *e, Type *named_type) {
case Entity_TypeName:
check_type_declaration(c, e, d->type_expr, named_type);
break;
case Entity_AliasName:
check_alias_declaration(c, e, d->type_expr, named_type);
break;
case Entity_Procedure:
check_procedure_declaration(c, e, d, true);
break;
@@ -763,7 +777,7 @@ void check_statement(Checker *c, AstNode *node, u32 flags) {
// Declarations
case AstNode_VariableDeclaration: {
auto *vd = &node->variable_declaration;
isize entity_count = vd->name_list_count;
isize entity_count = vd->name_count;
isize entity_index = 0;
Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
switch (vd->kind) {
@@ -820,7 +834,7 @@ void check_statement(Checker *c, AstNode *node, u32 flags) {
}
check_init_variables(c, entities, entity_count, vd->value_list, vd->value_list_count, make_string("variable declaration"));
check_init_variables(c, entities, entity_count, vd->value_list, vd->value_count, make_string("variable declaration"));
AstNode *name = vd->name_list;
for (isize i = 0; i < new_entity_count; i++, name = name->next) {
@@ -840,8 +854,8 @@ void check_statement(Checker *c, AstNode *node, u32 flags) {
check_constant_declaration(c, e, vd->type_expression, value);
}
isize lhs_count = vd->name_list_count;
isize rhs_count = vd->value_list_count;
isize lhs_count = vd->name_count;
isize rhs_count = vd->value_count;
// TODO(bill): Better error messages or is this good enough?
if (rhs_count == 0 && vd->type_expression == NULL) {
@@ -881,5 +895,13 @@ void check_statement(Checker *c, AstNode *node, u32 flags) {
add_entity(c, c->context.scope, name, e);
check_type_declaration(c, e, td->type_expression, NULL);
} break;
case AstNode_AliasDeclaration: {
auto *ad = &node->alias_declaration;
AstNode *name = ad->name;
Entity *e = make_entity_alias_name(c->allocator, c->context.scope, name->identifier.token, NULL);
add_entity(c, c->context.scope, name, e);
check_alias_declaration(c, e, ad->type_expression, NULL);
} break;
}
}
+42 -10
View File
@@ -60,6 +60,7 @@ enum TypeKind {
Type_Structure,
Type_Pointer,
Type_Named,
Type_Alias,
Type_Tuple,
Type_Procedure,
@@ -81,7 +82,7 @@ struct Type {
Entity **fields; // Entity_Variable
isize field_count; // == offset_count
i64 * offsets;
b32 offsets_set;
b32 are_offsets_set;
} structure;
struct { Type *element; } pointer;
struct {
@@ -89,6 +90,11 @@ struct Type {
Type * base;
Entity *type_name; // Entity_TypeName
} named;
struct {
String name;
Type * base;
Entity *alias_name; // Entity_AliasName
} alias;
struct {
Entity **variables; // Entity_Variable
isize variable_count;
@@ -97,15 +103,18 @@ struct Type {
Scope *scope;
Type * params; // Type_Tuple
Type * results; // Type_Tuple
isize params_count;
isize results_count;
isize param_count;
isize result_count;
} procedure;
};
};
Type *get_base_type(Type *t) {
while (t->kind == Type_Named) {
t = t->named.base;
while (t->kind == Type_Named || t->kind == Type_Alias) {
if (t->kind == Type_Named)
t = t->named.base;
else
t = t->alias.base;
}
return t;
}
@@ -113,6 +122,8 @@ Type *get_base_type(Type *t) {
void set_base_type(Type *t, Type *base) {
if (t && t->kind == Type_Named) {
t->named.base = base;
} else if (t && t->kind == Type_Alias) {
t->alias.base = base;
}
}
@@ -162,18 +173,26 @@ Type *make_type_named(gbAllocator a, String name, Type *base, Entity *type_name)
return t;
}
Type *make_type_alias(gbAllocator a, String name, Type *base, Entity *alias_name) {
Type *t = alloc_type(a, Type_Alias);
t->alias.name = name;
t->alias.base = base;
t->alias.alias_name = alias_name;
return t;
}
Type *make_type_tuple(gbAllocator a) {
Type *t = alloc_type(a, Type_Tuple);
return t;
}
Type *make_type_procedure(gbAllocator a, Scope *scope, Type *params, isize params_count, Type *results, isize results_count) {
Type *make_type_procedure(gbAllocator a, Scope *scope, Type *params, isize param_count, Type *results, isize result_count) {
Type *t = alloc_type(a, Type_Procedure);
t->procedure.scope = scope;
t->procedure.params = params;
t->procedure.params_count = params_count;
t->procedure.param_count = param_count;
t->procedure.results = results;
t->procedure.results_count = results_count;
t->procedure.result_count = result_count;
return t;
}
@@ -343,6 +362,10 @@ b32 are_types_identical(Type *x, Type *y) {
return are_types_identical(x->pointer.element, y->pointer.element);
break;
case Type_Alias:
return are_types_identical(get_base_type(x), y);
case Type_Named:
if (y->kind == Type_Named)
return x->named.base == y->named.base;
@@ -463,9 +486,9 @@ i64 *type_set_offsets_of(BaseTypeSizes s, gbAllocator allocator, Entity **fields
b32 type_set_offsets(BaseTypeSizes s, gbAllocator allocator, Type *t) {
GB_ASSERT(t->kind == Type_Structure);
if (!t->structure.offsets_set) {
if (!t->structure.are_offsets_set) {
t->structure.offsets = type_set_offsets_of(s, allocator, t->structure.fields, t->structure.field_count);
t->structure.offsets_set = true;
t->structure.are_offsets_set = true;
return true;
}
return false;
@@ -571,6 +594,15 @@ gbString write_type_to_string(gbString str, Type *type) {
}
break;
case Type_Alias:
if (type->alias.alias_name != NULL) {
str = gb_string_append_length(str, type->alias.name.text, type->alias.name.len);
} else {
// NOTE(bill): Just in case
str = gb_string_appendc(str, "<alias type>");
}
break;
case Type_Tuple:
if (type->tuple.variable_count > 0) {
for (isize i = 0; i < type->tuple.variable_count; i++) {
+13
View File
@@ -31,6 +31,19 @@ gb_inline b32 are_strings_equal(String a, String b) {
return false;
}
gb_inline b32 are_strings_equal_ignore_case(String a, String b) {
if (a.len == b.len) {
for (isize i = 0; i < a.len; i++) {
char x = cast(char)a.text[i];
char y = cast(char)b.text[i];
if (gb_char_to_lower(x) != gb_char_to_lower(y))
return false;
}
return true;
}
return false;
}
gb_inline isize string_extension_position(String str) {
isize dot_pos = -1;
+92 -69
View File
@@ -112,6 +112,7 @@ AstNode__DeclarationBegin,
AstNode_VariableDeclaration,
AstNode_ProcedureDeclaration,
AstNode_TypeDeclaration,
AstNode_AliasDeclaration,
AstNode_ImportDeclaration,
AstNode__DeclarationEnd,
@@ -234,21 +235,16 @@ struct AstNode {
AstNode *name_list;
AstNode *type_expression;
AstNode *value_list;
isize name_list_count, value_list_count;
isize name_count, value_count;
} variable_declaration;
struct {
AstNode *name_list;
isize name_list_count;
isize name_count;
AstNode *type_expression;
} field;
struct {
Token token;
AstNode *param_list; // AstNode_Field list
isize param_count;
AstNode *results_list; // type expression list
isize result_count;
} procedure_type;
// TODO(bill): Unify Procedure Declarations and Literals
struct {
DeclarationKind kind;
AstNode *name; // AstNode_Identifier
@@ -262,6 +258,11 @@ struct AstNode {
AstNode *name; // AstNode_Identifier
AstNode *type_expression;
} type_declaration;
struct {
Token token;
AstNode *name; // AstNode_Identifier
AstNode *type_expression;
} alias_declaration;
struct {
Token token;
Token filepath;
@@ -282,6 +283,13 @@ struct AstNode {
AstNode *field_list; // AstNode_Field
isize field_count;
} struct_type;
struct {
Token token;
AstNode *param_list; // AstNode_Field list
isize param_count;
AstNode *result_list; // type expression list
isize result_count;
} procedure_type;
};
};
@@ -374,6 +382,8 @@ Token ast_node_token(AstNode *node) {
return node->procedure_declaration.name->identifier.token;
case AstNode_TypeDeclaration:
return node->type_declaration.token;
case AstNode_AliasDeclaration:
return node->alias_declaration.token;
case AstNode_ImportDeclaration:
return node->import_declaration.token;
case AstNode_Field: {
@@ -717,31 +727,31 @@ gb_inline AstNode *make_bad_declaration(AstFile *f, Token begin, Token end) {
return result;
}
gb_inline AstNode *make_variable_declaration(AstFile *f, DeclarationKind kind, AstNode *name_list, isize name_list_count, AstNode *type_expression, AstNode *value_list, isize value_list_count) {
gb_inline AstNode *make_variable_declaration(AstFile *f, DeclarationKind kind, AstNode *name_list, isize name_count, AstNode *type_expression, AstNode *value_list, isize value_count) {
AstNode *result = make_node(f, AstNode_VariableDeclaration);
result->variable_declaration.kind = kind;
result->variable_declaration.name_list = name_list;
result->variable_declaration.name_list_count = name_list_count;
result->variable_declaration.name_count = name_count;
result->variable_declaration.type_expression = type_expression;
result->variable_declaration.value_list = value_list;
result->variable_declaration.value_list_count = value_list_count;
result->variable_declaration.value_count = value_count;
return result;
}
gb_inline AstNode *make_field(AstFile *f, AstNode *name_list, isize name_list_count, AstNode *type_expression) {
gb_inline AstNode *make_field(AstFile *f, AstNode *name_list, isize name_count, AstNode *type_expression) {
AstNode *result = make_node(f, AstNode_Field);
result->field.name_list = name_list;
result->field.name_list_count = name_list_count;
result->field.name_count = name_count;
result->field.type_expression = type_expression;
return result;
}
gb_inline AstNode *make_procedure_type(AstFile *f, Token token, AstNode *param_list, isize param_count, AstNode *results_list, isize result_count) {
gb_inline AstNode *make_procedure_type(AstFile *f, Token token, AstNode *param_list, isize param_count, AstNode *result_list, isize result_count) {
AstNode *result = make_node(f, AstNode_ProcedureType);
result->procedure_type.token = token;
result->procedure_type.param_list = param_list;
result->procedure_type.param_count = param_count;
result->procedure_type.results_list = results_list;
result->procedure_type.result_list = result_list;
result->procedure_type.result_count = result_count;
return result;
}
@@ -788,6 +798,15 @@ gb_inline AstNode *make_type_declaration(AstFile *f, Token token, AstNode *name,
return result;
}
gb_inline AstNode *make_alias_declaration(AstFile *f, Token token, AstNode *name, AstNode *type_expression) {
AstNode *result = make_node(f, AstNode_AliasDeclaration);
result->alias_declaration.token = token;
result->alias_declaration.name = name;
result->alias_declaration.type_expression = type_expression;
return result;
}
gb_inline AstNode *make_import_declaration(AstFile *f, Token token, Token filepath) {
AstNode *result = make_node(f, AstNode_ImportDeclaration);
result->import_declaration.token = token;
@@ -1293,7 +1312,7 @@ AstNode *parse_rhs_expression_list(AstFile *f, isize *list_count) {
return parse_expression_list(f, false, list_count);
}
AstNode *parse_declaration(AstFile *f, AstNode *name_list, isize name_list_count);
AstNode *parse_declaration(AstFile *f, AstNode *name_list, isize name_count);
AstNode *parse_simple_statement(AstFile *f) {
isize lhs_count = 0, rhs_count = 0;
@@ -1423,9 +1442,9 @@ AstNode *parse_type(AstFile *f) {
AstNode *parse_field_declaration(AstFile *f, AstScope *scope) {
AstNode *name_list = NULL;
isize name_list_count = 0;
name_list = parse_lhs_expression_list(f, &name_list_count);
if (name_list_count == 0)
isize name_count = 0;
name_list = parse_lhs_expression_list(f, &name_count);
if (name_count == 0)
ast_file_err(f, f->cursor[0], "Empty field declaration");
expect_token(f, Token_Colon);
@@ -1434,7 +1453,7 @@ AstNode *parse_field_declaration(AstFile *f, AstScope *scope) {
if (type_expression == NULL)
ast_file_err(f, f->cursor[0], "Expected a type for this field declaration");
AstNode *field = make_field(f, name_list, name_list_count, type_expression);
AstNode *field = make_field(f, name_list, name_count, type_expression);
add_ast_entity(f, scope, field, name_list);
return field;
}
@@ -1457,6 +1476,23 @@ AstNode *parse_procedure_type(AstFile *f, AstScope **scope_) {
}
AstNode *parse_parameter_list(AstFile *f, AstScope *scope, isize *param_count_) {
AstNode *param_list = NULL;
AstNode *param_list_curr = NULL;
isize param_count = 0;
while (f->cursor[0].kind == Token_Identifier) {
AstNode *field = parse_field_declaration(f, scope);
DLIST_APPEND(param_list, param_list_curr, field);
param_count += field->field.name_count;
if (f->cursor[0].kind != Token_Comma)
break;
next_token(f);
}
if (param_count_) *param_count_ = param_count;
return param_list;
}
AstNode *parse_identifier_or_type(AstFile *f) {
switch (f->cursor[0].kind) {
case Token_Identifier:
@@ -1480,24 +1516,15 @@ AstNode *parse_identifier_or_type(AstFile *f) {
case Token_struct: {
Token token = expect_token(f, Token_struct);
Token open, close;
AstNode *field_list = NULL;
AstNode *field_list_curr = NULL;
isize field_list_count = 0;
open = expect_token(f, Token_OpenBrace);
AstNode *params = NULL;
isize param_count = 0;
AstScope *scope = make_ast_scope(f, NULL); // NOTE(bill): The struct needs its own scope with NO parent
while (f->cursor[0].kind == Token_Identifier ||
f->cursor[0].kind == Token_Mul) {
DLIST_APPEND(field_list, field_list_curr, parse_field_declaration(f, scope));
expect_token(f, Token_Semicolon);
field_list_count++;
}
destroy_ast_scope(scope);
close = expect_token(f, Token_CloseBrace);
open = expect_token(f, Token_OpenBrace);
params = parse_parameter_list(f, scope, &param_count);
close = expect_token(f, Token_CloseBrace);
return make_struct_type(f, token, field_list, field_list_count);
return make_struct_type(f, token, params, param_count);
}
case Token_proc:
@@ -1514,6 +1541,7 @@ AstNode *parse_identifier_or_type(AstFile *f) {
return make_paren_expression(f, type_expression, open, close);
}
// TODO(bill): Why is this even allowed? Is this a parsing error?
case Token_Colon:
break;
@@ -1530,24 +1558,6 @@ AstNode *parse_identifier_or_type(AstFile *f) {
return NULL;
}
AstNode *parse_parameters(AstFile *f, AstScope *scope, isize *param_count_) {
AstNode *param_list = NULL;
AstNode *param_list_curr = NULL;
isize param_count = 0;
expect_token(f, Token_OpenParen);
while (f->cursor[0].kind != Token_CloseParen) {
AstNode *field = parse_field_declaration(f, scope);
DLIST_APPEND(param_list, param_list_curr, field);
param_count += field->field.name_list_count;
if (f->cursor[0].kind != Token_Comma)
break;
next_token(f);
}
expect_token(f, Token_CloseParen);
if (param_count_) *param_count_ = param_count;
return param_list;
}
AstNode *parse_results(AstFile *f, AstScope *scope, isize *result_count) {
if (allow_token(f, Token_ArrowRight)) {
@@ -1582,7 +1592,9 @@ Token parse_procedure_signature(AstFile *f, AstScope *scope,
AstNode **param_list, isize *param_count,
AstNode **result_list, isize *result_count) {
Token proc_token = expect_token(f, Token_proc);
*param_list = parse_parameters(f, scope, param_count);
expect_token(f, Token_OpenParen);
*param_list = parse_parameter_list(f, scope, param_count);
expect_token(f, Token_CloseParen);
*result_list = parse_results(f, scope, result_count);
return proc_token;
}
@@ -1626,10 +1638,10 @@ AstNode *parse_procedure_declaration(AstFile *f, Token proc_token, AstNode *name
return make_procedure_declaration(f, kind, name, proc_type, body, tag_list, tag_count);
}
AstNode *parse_declaration(AstFile *f, AstNode *name_list, isize name_list_count) {
AstNode *parse_declaration(AstFile *f, AstNode *name_list, isize name_count) {
AstNode *value_list = NULL;
AstNode *type_expression = NULL;
isize value_list_count = 0;
isize value_count = 0;
if (allow_token(f, Token_Colon)) {
type_expression = parse_identifier_or_type(f);
} else if (f->cursor[0].kind != Token_Eq && f->cursor[0].kind != Token_Semicolon) {
@@ -1647,26 +1659,20 @@ AstNode *parse_declaration(AstFile *f, AstNode *name_list, isize name_list_count
if (f->cursor[0].kind == Token_proc) { // NOTE(bill): Procedure declarations
Token proc_token = f->cursor[0];
AstNode *name = name_list;
if (name_list_count != 1) {
if (name_count != 1) {
ast_file_err(f, proc_token, "You can only declare one procedure at a time (at the moment)");
return make_bad_declaration(f, name->identifier.token, proc_token);
}
// TODO(bill): Allow for mutable procedures
if (declaration_kind != Declaration_Immutable) {
ast_file_err(f, proc_token, "Only immutable procedures are supported (at the moment)");
return make_bad_declaration(f, name->identifier.token, proc_token);
}
AstNode *procedure_declaration = parse_procedure_declaration(f, proc_token, name, declaration_kind);
add_ast_entity(f, f->curr_scope, procedure_declaration, name_list);
return procedure_declaration;
} else {
value_list = parse_rhs_expression_list(f, &value_list_count);
if (value_list_count > name_list_count) {
value_list = parse_rhs_expression_list(f, &value_count);
if (value_count > name_count) {
ast_file_err(f, f->cursor[0], "Too many values on the right hand side of the declaration");
} else if (value_list_count < name_list_count &&
} else if (value_count < name_count &&
declaration_kind == Declaration_Immutable) {
ast_file_err(f, f->cursor[0], "All constant declarations must be defined");
} else if (value_list == NULL) {
@@ -1681,7 +1687,7 @@ AstNode *parse_declaration(AstFile *f, AstNode *name_list, isize name_list_count
return make_bad_declaration(f, f->cursor[0], f->cursor[0]);
}
} else if (declaration_kind == Declaration_Immutable) {
if (type_expression == NULL && value_list == NULL && name_list_count > 0) {
if (type_expression == NULL && value_list == NULL && name_count > 0) {
ast_file_err(f, f->cursor[0], "Missing constant value");
return make_bad_declaration(f, f->cursor[0], f->cursor[0]);
}
@@ -1692,7 +1698,7 @@ AstNode *parse_declaration(AstFile *f, AstNode *name_list, isize name_list_count
return make_bad_declaration(f, begin, f->cursor[0]);
}
AstNode *variable_declaration = make_variable_declaration(f, declaration_kind, name_list, name_list_count, type_expression, value_list, value_list_count);
AstNode *variable_declaration = make_variable_declaration(f, declaration_kind, name_list, name_count, type_expression, value_list, value_count);
add_ast_entity(f, f->curr_scope, variable_declaration, name_list);
return variable_declaration;
}
@@ -1858,6 +1864,21 @@ AstNode *parse_type_declaration(AstFile *f) {
return type_declaration;
}
AstNode *parse_alias_declaration(AstFile *f) {
Token token = expect_token(f, Token_alias);
AstNode *name = parse_identifier(f);
expect_token(f, Token_Colon);
AstNode *type_expression = parse_type(f);
AstNode *alias_declaration = make_alias_declaration(f, token, name, type_expression);
if (type_expression->kind != AstNode_StructType &&
type_expression->kind != AstNode_ProcedureType)
expect_token(f, Token_Semicolon);
return alias_declaration;
}
AstNode *parse_import_declaration(AstFile *f) {
Token token = expect_token(f, Token_import);
Token filepath = expect_token(f, Token_String);
@@ -1874,6 +1895,8 @@ AstNode *parse_statement(AstFile *f) {
switch (token.kind) {
case Token_type:
return parse_type_declaration(f);
case Token_alias:
return parse_alias_declaration(f);
case Token_import:
return parse_import_declaration(f);
+2 -2
View File
@@ -166,10 +166,10 @@ void print_ast(AstNode *node, isize indent) {
print_indent(indent);
gb_printf("(type:proc)(%td -> %td)\n", node->procedure_type.param_count, node->procedure_type.result_count);
print_ast(node->procedure_type.param_list, indent+1);
if (node->procedure_type.results_list) {
if (node->procedure_type.result_list) {
print_indent(indent+1);
gb_printf("->\n");
print_ast(node->procedure_type.results_list, indent+1);
print_ast(node->procedure_type.result_list, indent+1);
}
break;
case AstNode_Field:
+3
View File
@@ -102,6 +102,7 @@ Token__OperatorEnd,
Token__KeywordBegin,
Token_type,
Token_alias,
Token_proc,
Token_match, // TODO(bill): switch vs match?
Token_break,
@@ -189,6 +190,7 @@ char const *TOKEN_STRINGS[] = {
"_OperatorEnd",
"_KeywordBegin",
"type",
"alias",
"proc",
"match",
"break",
@@ -697,6 +699,7 @@ Token tokenizer_get_token(Tokenizer *t) {
KWB
KWT("type", Token_type);
KWT("alias", Token_alias);
KWT("proc", Token_proc);
KWT("match", Token_match);
KWT("break", Token_break);