Minor refactor and basic library

This commit is contained in:
gingerBill
2016-08-05 15:17:23 +01:00
parent 2aaef48c5c
commit 4a303b5c3e
18 changed files with 708 additions and 608 deletions
+37 -33
View File
@@ -20,7 +20,7 @@ struct Operand {
Type *type;
ExactValue value;
AstNode *expr;
BuiltinProcedureId builtin_id;
BuiltinProcId builtin_id;
};
struct TypeAndValue {
@@ -110,32 +110,34 @@ enum ExpressionKind {
Expression_Statement,
};
enum BuiltinProcedureId {
BuiltinProcedure_Invalid,
enum BuiltinProcId {
BuiltinProc_Invalid,
BuiltinProcedure_size_of,
BuiltinProcedure_size_of_val,
BuiltinProcedure_align_of,
BuiltinProcedure_align_of_val,
BuiltinProcedure_offset_of,
BuiltinProcedure_offset_of_val,
BuiltinProcedure_static_assert,
BuiltinProcedure_len,
BuiltinProcedure_cap,
BuiltinProcedure_copy,
BuiltinProcedure_print,
BuiltinProcedure_println,
BuiltinProc_size_of,
BuiltinProc_size_of_val,
BuiltinProc_align_of,
BuiltinProc_align_of_val,
BuiltinProc_offset_of,
BuiltinProc_offset_of_val,
BuiltinProc_static_assert,
BuiltinProc_len,
BuiltinProc_cap,
BuiltinProc_copy,
BuiltinProc_append,
BuiltinProc_print,
BuiltinProc_println,
BuiltinProcedure_Count,
BuiltinProc_Count,
};
struct BuiltinProcedure {
struct BuiltinProc {
String name;
isize arg_count;
b32 variadic;
ExpressionKind kind;
};
gb_global BuiltinProcedure builtin_procedures[BuiltinProcedure_Count] = {
gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
{STR_LIT(""), 0, false, Expression_Statement},
{STR_LIT("size_of"), 1, false, Expression_Expression},
{STR_LIT("size_of_val"), 1, false, Expression_Expression},
{STR_LIT("align_of"), 1, false, Expression_Expression},
@@ -143,9 +145,11 @@ gb_global BuiltinProcedure builtin_procedures[BuiltinProcedure_Count] = {
{STR_LIT("offset_of"), 2, false, Expression_Expression},
{STR_LIT("offset_of_val"), 1, false, Expression_Expression},
{STR_LIT("static_assert"), 1, false, Expression_Statement},
{STR_LIT("len"), 1, false, Expression_Expression},
{STR_LIT("cap"), 1, false, Expression_Expression},
{STR_LIT("copy"), 2, false, Expression_Expression},
{STR_LIT("append"), 2, false, Expression_Expression},
{STR_LIT("print"), 1, true, Expression_Statement},
{STR_LIT("println"), 1, true, Expression_Statement},
};
@@ -172,14 +176,14 @@ struct Checker {
AstFile * curr_ast_file;
BaseTypeSizes sizes;
Scope * global_scope;
gbArray(ProcedureInfo) procedures; // NOTE(bill): Procedures to check
gbArray(ProcedureInfo) procs; // NOTE(bill): Procedures to check
gbArena arena;
gbAllocator allocator;
CheckerContext context;
gbArray(Type *) procedure_stack;
gbArray(Type *) proc_stack;
b32 in_defer; // TODO(bill): Actually handle correctly
ErrorCollector error_collector;
@@ -334,10 +338,10 @@ void init_universal_scope(void) {
add_global_constant(a, make_string("null"), t_untyped_pointer, make_exact_value_pointer(NULL));
// Builtin Procedures
for (isize i = 0; i < gb_count_of(builtin_procedures); i++) {
BuiltinProcedureId id = cast(BuiltinProcedureId)i;
for (isize i = 0; i < gb_count_of(builtin_procs); i++) {
BuiltinProcId id = cast(BuiltinProcId)i;
Token token = {Token_Identifier};
token.string = builtin_procedures[i].name;
token.string = builtin_procs[i].name;
Entity *entity = alloc_entity(a, Entity_Builtin, NULL, token, t_invalid);
entity->builtin.id = id;
add_global_entity(entity);
@@ -376,8 +380,8 @@ void init_checker(Checker *c, Parser *parser) {
c->sizes.word_size = 8;
c->sizes.max_align = 8;
gb_array_init(c->procedure_stack, a);
gb_array_init(c->procedures, a);
gb_array_init(c->proc_stack, a);
gb_array_init(c->procs, a);
// NOTE(bill): Is this big enough or too small?
isize item_size = gb_max(gb_max(gb_size_of(Entity), gb_size_of(Type)), gb_size_of(Scope));
@@ -397,8 +401,8 @@ void init_checker(Checker *c, Parser *parser) {
void destroy_checker(Checker *c) {
destroy_checker_info(&c->info);
destroy_scope(c->global_scope);
gb_array_free(c->procedure_stack);
gb_array_free(c->procedures);
gb_array_free(c->proc_stack);
gb_array_free(c->procs);
gb_arena_free(&c->arena);
}
@@ -500,7 +504,7 @@ void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *dec
info.decl = decl;
info.type = type;
info.body = body;
gb_array_append(c->procedures, info);
gb_array_append(c->procs, info);
}
void check_add_deferred_stmt(Checker *c, AstNode *stmt) {
@@ -509,12 +513,12 @@ void check_add_deferred_stmt(Checker *c, AstNode *stmt) {
gb_array_append(c->context.scope->deferred_stmts, stmt);
}
void push_procedure(Checker *c, Type *procedure_type) {
gb_array_append(c->procedure_stack, procedure_type);
void push_procedure(Checker *c, Type *type) {
gb_array_append(c->proc_stack, type);
}
void pop_procedure(Checker *c) {
gb_array_pop(c->procedure_stack);
gb_array_pop(c->proc_stack);
}
void add_curr_ast_file(Checker *c, AstFile *file) {
@@ -655,8 +659,8 @@ void check_parsed_files(Checker *c) {
// Check procedure bodies
gb_for_array(i, c->procedures) {
ProcedureInfo *pi = &c->procedures[i];
gb_for_array(i, c->procs) {
ProcedureInfo *pi = &c->procs[i];
add_curr_ast_file(c, pi->file);
check_proc_body(c, pi->token, pi->decl, pi->type, pi->body);
}
+3 -3
View File
@@ -1,6 +1,6 @@
struct Scope;
struct Checker;
enum BuiltinProcedureId;
enum BuiltinProcId;
#define ENTITY_KINDS \
ENTITY_KIND(Invalid), \
@@ -47,7 +47,7 @@ struct Entity {
struct {} type_name;
struct {} alias_name;
struct {} procedure;
struct { BuiltinProcedureId id; } builtin;
struct { BuiltinProcId id; } builtin;
};
};
@@ -105,7 +105,7 @@ Entity *make_entity_procedure(gbAllocator a, Scope *parent, Token token, Type *s
return entity;
}
Entity *make_entity_builtin(gbAllocator a, Scope *parent, Token token, Type *type, BuiltinProcedureId id) {
Entity *make_entity_builtin(gbAllocator a, Scope *parent, Token token, Type *type, BuiltinProcId id) {
Entity *entity = alloc_entity(a, Entity_Builtin, parent, token, type);
entity->builtin.id = id;
return entity;
+93 -56
View File
@@ -105,11 +105,6 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *list, isize list_coun
Entity *param = make_entity_param(c->allocator, scope, token, type);
// NOTE(bill): No need to record
variables[variable_index++] = param;
if (get_base_type(type)->kind == Type_Array) {
// TODO(bill): Should I allow array's to returned?
error(&c->error_collector, token, "You cannot return an array from a procedure");
}
}
tuple->tuple.variables = variables;
tuple->tuple.variable_count = list_count;
@@ -129,11 +124,11 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
Type *params = check_get_params(c, c->context.scope, pt->param_list, param_count);
Type *results = check_get_results(c, c->context.scope, pt->result_list, result_count);
type->procedure.scope = c->context.scope;
type->procedure.params = params;
type->procedure.param_count = pt->param_count;
type->procedure.results = results;
type->procedure.result_count = pt->result_count;
type->proc.scope = c->context.scope;
type->proc.params = params;
type->proc.param_count = pt->param_count;
type->proc.results = results;
type->proc.result_count = pt->result_count;
}
@@ -292,7 +287,7 @@ Type *check_type_expr_extra(Checker *c, AstNode *e, Type *named_type) {
case_end;
case_ast_node(pt, ProcType, e);
Type *t = alloc_type(c->allocator, Type_Procedure);
Type *t = alloc_type(c->allocator, Type_Proc);
set_base_type(named_type, t);
check_open_scope(c, e);
check_procedure_type(c, t, e);
@@ -384,7 +379,7 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) {
case_end;
case_ast_node(pt, ProcType, e);
type = alloc_type(c->allocator, Type_Procedure);
type = alloc_type(c->allocator, Type_Proc);
set_base_type(named_type, type);
check_procedure_type(c, type, e);
goto end;
@@ -958,7 +953,7 @@ Entity *lookup_field(Type *type, AstNode *field_node, isize *index = NULL) {
GB_ASSERT(field_node->kind == AstNode_Ident);
type = get_base_type(type);
if (type->kind == Type_Pointer)
type = get_base_type(type->pointer.element);
type = get_base_type(type->pointer.elem);
ast_node(i, Ident, field_node);
String field_str = i->token.string;
@@ -1016,7 +1011,7 @@ void check_selector(Checker *c, Operand *operand, AstNode *node) {
b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) {
GB_ASSERT(call->kind == AstNode_CallExpr);
ast_node(ce, CallExpr, call);
BuiltinProcedure *bp = &builtin_procedures[id];
BuiltinProc *bp = &builtin_procs[id];
{
char *err = NULL;
if (ce->arg_list_count < bp->arg_count)
@@ -1033,9 +1028,9 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
}
switch (id) {
case BuiltinProcedure_size_of:
case BuiltinProcedure_align_of:
case BuiltinProcedure_offset_of:
case BuiltinProc_size_of:
case BuiltinProc_align_of:
case BuiltinProc_offset_of:
// NOTE(bill): The first arg is a Type, this will be checked case by case
break;
default:
@@ -1043,7 +1038,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
}
switch (id) {
case BuiltinProcedure_size_of: {
case BuiltinProc_size_of: {
// size_of :: proc(Type)
Type *type = check_type(c, ce->arg_list);
if (!type) {
@@ -1057,7 +1052,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
} break;
case BuiltinProcedure_size_of_val:
case BuiltinProc_size_of_val:
// size_of_val :: proc(val)
check_assignment(c, operand, NULL, make_string("argument of `size_of`"));
if (operand->mode == Addressing_Invalid)
@@ -1068,7 +1063,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
operand->type = t_int;
break;
case BuiltinProcedure_align_of: {
case BuiltinProc_align_of: {
// align_of :: proc(Type)
Type *type = check_type(c, ce->arg_list);
if (!type) {
@@ -1080,7 +1075,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
operand->type = t_int;
} break;
case BuiltinProcedure_align_of_val:
case BuiltinProc_align_of_val:
// align_of_val :: proc(val)
check_assignment(c, operand, NULL, make_string("argument of `align_of`"));
if (operand->mode == Addressing_Invalid)
@@ -1091,7 +1086,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
operand->type = t_int;
break;
case BuiltinProcedure_offset_of: {
case BuiltinProc_offset_of: {
// offset_val :: proc(Type, field)
Type *type = get_base_type(check_type(c, ce->arg_list));
AstNode *field_arg = unparen_expr(ce->arg_list->next);
@@ -1122,7 +1117,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
operand->type = t_int;
} break;
case BuiltinProcedure_offset_of_val: {
case BuiltinProc_offset_of_val: {
// offset_val :: proc(val)
AstNode *arg = unparen_expr(ce->arg_list);
if (arg->kind != AstNode_SelectorExpr) {
@@ -1140,7 +1135,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
if (get_base_type(type)->kind == Type_Pointer) {
Type *p = get_base_type(type);
if (get_base_type(p)->kind == Type_Structure)
type = p->pointer.element;
type = p->pointer.elem;
}
isize index = 0;
@@ -1158,7 +1153,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
operand->type = t_int;
} break;
case BuiltinProcedure_static_assert:
case BuiltinProc_static_assert:
// static_assert :: proc(cond: bool)
// TODO(bill): Should `static_assert` and `assert` be unified?
@@ -1180,8 +1175,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
break;
// TODO(bill): Should these be procedures and are their names appropriate?
case BuiltinProcedure_len:
case BuiltinProcedure_cap: {
case BuiltinProc_len:
case BuiltinProc_cap: {
Type *t = get_base_type(operand->type);
AddressingMode mode = Addressing_Invalid;
@@ -1189,7 +1184,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
switch (t->kind) {
case Type_Basic:
if (id == BuiltinProcedure_len) {
if (id == BuiltinProc_len) {
if (is_type_string(t)) {
if (operand->mode == Addressing_Constant) {
mode = Addressing_Constant;
@@ -1226,14 +1221,13 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
} break;
// TODO(bill): copy() pointer version?
case BuiltinProcedure_copy: {
case BuiltinProc_copy: {
// copy :: proc(x, y: []Type) -> int
Type *dest_type = NULL, *src_type = NULL;
Type *d = get_base_type(operand->type);
if (d->kind == Type_Slice)
dest_type = d->slice.element;
dest_type = d->slice.elem;
Operand op = {};
check_expr(c, &op, ce->arg_list->next);
@@ -1241,7 +1235,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
return false;
Type *s = get_base_type(op.type);
if (s->kind == Type_Slice)
src_type = s->slice.element;
src_type = s->slice.elem;
if (dest_type == NULL || src_type == NULL) {
error(&c->error_collector, ast_node_token(call), "`copy` only expects slices as arguments");
@@ -1258,20 +1252,56 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
defer (gb_string_free(d_str));
defer (gb_string_free(s_str));
error(&c->error_collector, ast_node_token(call),
"Arguments to `copy`, %s, %s, have different element types: %s vs %s",
"Arguments to `copy`, %s, %s, have different elem types: %s vs %s",
d_arg, s_arg, d_str, s_str);
return false;
}
operand->type = t_int; // Returns number of elements copied
operand->type = t_int; // Returns number of elems copied
operand->mode = Addressing_Value;
} break;
case BuiltinProcedure_print:
case BuiltinProcedure_println: {
case BuiltinProc_append: {
// append :: proc(x : ^[]Type, y : Type) -> bool
Type *x_type = NULL, *y_type = NULL;
x_type = get_base_type(operand->type);
Operand op = {};
check_expr(c, &op, ce->arg_list->next);
if (op.mode == Addressing_Invalid)
return false;
y_type = get_base_type(op.type);
if (!(is_type_pointer(x_type) && is_type_slice(x_type->pointer.elem))) {
error(&c->error_collector, ast_node_token(call), "First argument to `append` must be a pointer to a slice");
return false;
}
Type *elem_type = x_type->pointer.elem->slice.elem;
if (!check_is_assignable_to(c, &op, elem_type)) {
gbString d_arg = expr_to_string(ce->arg_list);
gbString s_arg = expr_to_string(ce->arg_list->next);
gbString d_str = type_to_string(elem_type);
gbString s_str = type_to_string(y_type);
defer (gb_string_free(d_arg));
defer (gb_string_free(s_arg));
defer (gb_string_free(d_str));
defer (gb_string_free(s_str));
error(&c->error_collector, ast_node_token(call),
"Arguments to `append`, %s, %s, have different element types: %s vs %s",
d_arg, s_arg, d_str, s_str);
return false;
}
operand->type = t_bool; // Returns if it was successful
operand->mode = Addressing_Value;
} break;
case BuiltinProc_print:
case BuiltinProc_println: {
for (AstNode *arg = ce->arg_list; arg != NULL; arg = arg->next) {
// TOOD(bill): `check_assignment` doesn't allow tuples at the moment, should it?
// Or should we destruct the tuple and use each element?
// Or should we destruct the tuple and use each elem?
check_assignment(c, operand, NULL, make_string("argument"));
if (operand->mode == Addressing_Invalid)
return false;
@@ -1285,14 +1315,14 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode *call) {
GB_ASSERT(call->kind == AstNode_CallExpr);
GB_ASSERT(proc_type->kind == Type_Procedure);
GB_ASSERT(proc_type->kind == Type_Proc);
ast_node(ce, CallExpr, call);
isize error_code = 0;
isize param_index = 0;
isize param_count = 0;
if (proc_type->procedure.params)
param_count = proc_type->procedure.params->tuple.variable_count;
if (proc_type->proc.params)
param_count = proc_type->proc.params->tuple.variable_count;
if (ce->arg_list_count == 0 && param_count == 0)
return;
@@ -1300,7 +1330,7 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
if (ce->arg_list_count > param_count) {
error_code = +1;
} else {
Entity **sig_params = proc_type->procedure.params->tuple.variables;
Entity **sig_params = proc_type->proc.params->tuple.variables;
AstNode *call_arg = ce->arg_list;
for (; call_arg != NULL; call_arg = call_arg->next) {
check_multi_expr(c, operand, call_arg);
@@ -1376,11 +1406,11 @@ ExpressionKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
if (!check_builtin_procedure(c, operand, call, id))
operand->mode = Addressing_Invalid;
operand->expr = call;
return builtin_procedures[id].kind;
return builtin_procs[id].kind;
}
Type *proc_type = get_base_type(operand->type);
if (proc_type == NULL || proc_type->kind != Type_Procedure) {
if (proc_type == NULL || proc_type->kind != Type_Proc) {
AstNode *e = operand->expr;
gbString str = expr_to_string(e);
defer (gb_string_free(str));
@@ -1395,7 +1425,7 @@ ExpressionKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
check_call_arguments(c, operand, proc_type, call);
auto *proc = &proc_type->procedure;
auto *proc = &proc_type->proc;
if (proc->result_count == 0) {
operand->mode = Addressing_NoValue;
} else if (proc->result_count == 1) {
@@ -1448,6 +1478,14 @@ b32 check_castable_to(Checker *c, Operand *operand, Type *y) {
return true;
}
// []byte/[]u8 <-> string
if (is_type_byte_slice(xb) && is_type_string(yb)) {
return true;
}
if (is_type_string(xb) && is_type_byte_slice(yb)) {
return true;
}
return false;
}
@@ -1590,13 +1628,13 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ
case Type_Slice:
case Type_Array:
{
Type *element_type = NULL;
Type *elem_type = NULL;
String context_name = {};
if (t->kind == Type_Slice) {
element_type = t->slice.element;
elem_type = t->slice.elem;
context_name = make_string("slice literal");
} else {
element_type = t->array.element;
elem_type = t->array.elem;
context_name = make_string("array literal");
}
@@ -1612,8 +1650,8 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ
}
Operand o = {};
check_expr_with_type_hint(c, &o, e, element_type);
check_assignment(c, &o, element_type, context_name);
check_expr_with_type_hint(c, &o, e, elem_type);
check_assignment(c, &o, elem_type, context_name);
}
if (max < index)
max = index;
@@ -1693,19 +1731,19 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ
max_count = t->array.count;
if (o->mode != Addressing_Variable)
o->mode = Addressing_Value;
o->type = t->array.element;
o->type = t->array.elem;
break;
case Type_Slice:
valid = true;
o->type = t->slice.element;
o->type = t->slice.elem;
o->mode = Addressing_Variable;
break;
case Type_Pointer:
valid = true;
o->mode = Addressing_Variable;
o->type = get_base_type(t->pointer.element);
o->type = get_base_type(t->pointer.elem);
break;
}
@@ -1757,7 +1795,7 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ
gb_string_free(str);
goto error;
}
o->type = make_type_slice(c->allocator, t->array.element);
o->type = make_type_slice(c->allocator, t->array.elem);
o->mode = Addressing_Value;
break;
@@ -1768,7 +1806,7 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ
case Type_Pointer:
valid = true;
o->type = make_type_slice(c->allocator, get_base_type(t->pointer.element));
o->type = make_type_slice(c->allocator, get_base_type(t->pointer.elem));
o->mode = Addressing_Value;
break;
}
@@ -1832,7 +1870,7 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ
Type *t = get_base_type(o->type);
if (t->kind == Type_Pointer) {
o->mode = Addressing_Variable;
o->type = t->pointer.element;
o->type = t->pointer.elem;
} else {
gbString str = expr_to_string(o->expr);
error(&c->error_collector, ast_node_token(o->expr), "Cannot dereference `%s`", str);
@@ -1911,7 +1949,6 @@ void check_multi_expr(Checker *c, Operand *o, AstNode *e) {
o->mode = Addressing_Invalid;
}
// TODO(bill): Should I remove this entirely?
void check_not_tuple(Checker *c, Operand *o) {
if (o->mode == Addressing_Value) {
// NOTE(bill): Tuples are not first class thus never named
+9 -9
View File
@@ -108,13 +108,13 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type) {
return true;
if (sb->kind == Type_Array && tb->kind == Type_Array) {
if (are_types_identical(sb->array.element, tb->array.element)) {
if (are_types_identical(sb->array.elem, tb->array.elem)) {
return sb->array.count == tb->array.count;
}
}
if (sb->kind == Type_Slice && tb->kind == Type_Slice) {
if (are_types_identical(sb->slice.element, tb->slice.element)) {
if (are_types_identical(sb->slice.elem, tb->slice.elem)) {
return true;
}
}
@@ -391,7 +391,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
push_procedure(c, type);
ast_node(bs, BlockStmt, body);
check_stmt_list(c, bs->list, 0);
if (type->procedure.result_count > 0) {
if (type->proc.result_count > 0) {
if (!check_is_terminating(c, body)) {
error(&c->error_collector, bs->close, "Missing return statement at the end of the procedure");
}
@@ -404,7 +404,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) {
GB_ASSERT(e->type == NULL);
Type *proc_type = make_type_procedure(c->allocator, e->parent, NULL, 0, NULL, 0);
Type *proc_type = make_type_proc(c->allocator, e->parent, NULL, 0, NULL, 0);
e->type = proc_type;
ast_node(pd, ProcDecl, d->proc_decl);
@@ -701,7 +701,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
case_end;
case_ast_node(rs, ReturnStmt, node);
GB_ASSERT(gb_array_count(c->procedure_stack) > 0);
GB_ASSERT(gb_array_count(c->proc_stack) > 0);
if (c->in_defer) {
error(&c->error_collector, rs->token, "You cannot `return` within a defer statement");
@@ -709,17 +709,17 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
break;
}
Type *proc_type = c->procedure_stack[gb_array_count(c->procedure_stack)-1];
Type *proc_type = c->proc_stack[gb_array_count(c->proc_stack)-1];
isize result_count = 0;
if (proc_type->procedure.results)
result_count = proc_type->procedure.results->tuple.variable_count;
if (proc_type->proc.results)
result_count = proc_type->proc.results->tuple.variable_count;
if (result_count != rs->result_count) {
error(&c->error_collector, rs->token, "Expected %td return %s, got %td",
result_count,
(result_count != 1 ? "values" : "value"),
rs->result_count);
} else if (result_count > 0) {
auto *tuple = &proc_type->procedure.results->tuple;
auto *tuple = &proc_type->proc.results->tuple;
check_init_variables(c, tuple->variables, tuple->variable_count,
rs->result_list, rs->result_count, make_string("return statement"));
}
+53 -39
View File
@@ -62,7 +62,7 @@ struct BasicType {
TYPE_KIND(Named), \
TYPE_KIND(Alias), \
TYPE_KIND(Tuple), \
TYPE_KIND(Procedure), \
TYPE_KIND(Proc), \
TYPE_KIND(Count),
enum TypeKind {
@@ -82,11 +82,11 @@ struct Type {
union {
BasicType basic;
struct {
Type *element;
Type *elem;
i64 count;
} array;
struct {
Type *element;
Type *elem;
} slice;
struct {
// Theses are arrays
@@ -95,7 +95,7 @@ struct Type {
i64 * offsets;
b32 are_offsets_set;
} structure;
struct { Type *element; } pointer;
struct { Type *elem; } pointer;
struct {
String name;
Type * base;
@@ -116,7 +116,7 @@ struct Type {
Type * results; // Type_Tuple
isize param_count;
isize result_count;
} procedure;
} proc;
};
};
@@ -152,16 +152,16 @@ Type *make_type_basic(gbAllocator a, BasicType basic) {
return t;
}
Type *make_type_array(gbAllocator a, Type *element, i64 count) {
Type *make_type_array(gbAllocator a, Type *elem, i64 count) {
Type *t = alloc_type(a, Type_Array);
t->array.element = element;
t->array.elem = elem;
t->array.count = count;
return t;
}
Type *make_type_slice(gbAllocator a, Type *element) {
Type *make_type_slice(gbAllocator a, Type *elem) {
Type *t = alloc_type(a, Type_Slice);
t->array.element = element;
t->array.elem = elem;
return t;
}
@@ -170,9 +170,9 @@ Type *make_type_structure(gbAllocator a) {
return t;
}
Type *make_type_pointer(gbAllocator a, Type *element) {
Type *make_type_pointer(gbAllocator a, Type *elem) {
Type *t = alloc_type(a, Type_Pointer);
t->pointer.element = element;
t->pointer.elem = elem;
return t;
}
@@ -197,20 +197,20 @@ Type *make_type_tuple(gbAllocator a) {
return t;
}
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.param_count = param_count;
t->procedure.results = results;
t->procedure.result_count = result_count;
Type *make_type_proc(gbAllocator a, Scope *scope, Type *params, isize param_count, Type *results, isize result_count) {
Type *t = alloc_type(a, Type_Proc);
t->proc.scope = scope;
t->proc.params = params;
t->proc.param_count = param_count;
t->proc.results = results;
t->proc.result_count = result_count;
return t;
}
Type *type_deref(Type *t) {
if (t != NULL && t->kind == Type_Pointer)
return t->pointer.element;
return t->pointer.elem;
return t;
}
@@ -338,12 +338,26 @@ b32 is_type_int_or_uint(Type *t) {
return (t->basic.kind == Basic_int) || (t->basic.kind == Basic_uint);
return false;
}
b32 is_type_rawptr(Type *t) {
if (t->kind == Type_Basic)
return t->basic.kind == Basic_rawptr;
return false;
}
b32 is_type_byte(Type *t) {
if (t->kind == Type_Basic)
return t->basic.kind == Basic_byte;
return false;
}
b32 is_type_slice(Type *t) {
return t->kind == Type_Slice;
}
b32 is_type_byte_slice(Type *t) {
if (t->kind == Type_Slice)
return is_type_byte(t->slice.elem);
return false;
}
b32 is_type_comparable(Type *t) {
t = get_base_type(t);
@@ -360,7 +374,7 @@ b32 is_type_comparable(Type *t) {
return true;
} break;
case Type_Array:
return is_type_comparable(t->array.element);
return is_type_comparable(t->array.elem);
}
return false;
}
@@ -382,7 +396,7 @@ b32 are_types_identical(Type *x, Type *y) {
case Type_Array:
if (y->kind == Type_Array)
return (x->array.count == y->array.count) && are_types_identical(x->array.element, y->array.element);
return (x->array.count == y->array.count) && are_types_identical(x->array.elem, y->array.elem);
break;
case Type_Structure:
@@ -401,7 +415,7 @@ b32 are_types_identical(Type *x, Type *y) {
case Type_Pointer:
if (y->kind == Type_Pointer)
return are_types_identical(x->pointer.element, y->pointer.element);
return are_types_identical(x->pointer.elem, y->pointer.elem);
break;
@@ -426,10 +440,10 @@ b32 are_types_identical(Type *x, Type *y) {
}
break;
case Type_Procedure:
if (y->kind == Type_Procedure) {
return are_types_identical(x->procedure.params, y->procedure.params) &&
are_types_identical(x->procedure.results, y->procedure.results);
case Type_Proc:
if (y->kind == Type_Proc) {
return are_types_identical(x->proc.params, y->proc.params) &&
are_types_identical(x->proc.results, y->proc.results);
}
break;
}
@@ -457,7 +471,7 @@ Type *default_type(Type *type) {
// NOTE(bill): Internal sizes of certain types
// string: 2*word_size (ptr+len)
// slice: 3*word_size (ptr+len+cap)
// array: count*size_of(element) aligned
// array: count*size_of(elem) aligned
// NOTE(bill): Alignment of structures and other types are to be compatible with C
@@ -497,7 +511,7 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
switch (t->kind) {
case Type_Array:
return type_align_of(s, allocator, t->array.element);
return type_align_of(s, allocator, t->array.elem);
case Type_Structure: {
i64 max = 1;
for (isize i = 0; i < t->structure.field_count; i++) {
@@ -555,8 +569,8 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
i64 count = t->array.count;
if (count == 0)
return 0;
i64 align = type_align_of(s, allocator, t->array.element);
i64 size = type_size_of(s, allocator, t->array.element);
i64 align = type_align_of(s, allocator, t->array.elem);
i64 size = type_size_of(s, allocator, t->array.elem);
i64 alignment = align_formula(size, align);
return alignment*(count-1) + size;
} break;
@@ -600,12 +614,12 @@ gbString write_type_to_string(gbString str, Type *type) {
case Type_Array:
str = gb_string_appendc(str, gb_bprintf("[%td]", type->array.count));
str = write_type_to_string(str, type->array.element);
str = write_type_to_string(str, type->array.elem);
break;
case Type_Slice:
str = gb_string_appendc(str, "[]");
str = write_type_to_string(str, type->array.element);
str = write_type_to_string(str, type->array.elem);
break;
case Type_Structure: {
@@ -624,7 +638,7 @@ gbString write_type_to_string(gbString str, Type *type) {
case Type_Pointer:
str = gb_string_appendc(str, "^");
str = write_type_to_string(str, type->pointer.element);
str = write_type_to_string(str, type->pointer.elem);
break;
case Type_Named:
@@ -657,14 +671,14 @@ gbString write_type_to_string(gbString str, Type *type) {
}
break;
case Type_Procedure:
case Type_Proc:
str = gb_string_appendc(str, "proc(");
if (type->procedure.params)
str = write_type_to_string(str, type->procedure.params);
if (type->proc.params)
str = write_type_to_string(str, type->proc.params);
str = gb_string_appendc(str, ")");
if (type->procedure.results) {
if (type->proc.results) {
str = gb_string_appendc(str, " -> ");
str = write_type_to_string(str, type->procedure.results);
str = write_type_to_string(str, type->proc.results);
}
break;
}