Code clean up of call arguments

This commit is contained in:
Ginger Bill
2016-10-03 23:28:37 +01:00
parent f6589d9814
commit fee504636f
4 changed files with 104 additions and 144 deletions

View File

@@ -5,12 +5,5 @@
#import "game.odin"
main :: proc() {
Vector3 :: struct {
x, y, z: f32
}
Entity :: struct {
guid: u64
position: Vector3
}
fmt.println("Hellope")
}

View File

@@ -85,10 +85,13 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
return true;
}
if (is_type_pointer(dst) && is_type_rawptr(src)) {
return true;
}
// ^T <- rawptr
// TODO(bill): Should C-style (not C++) pointer cast be allowed?
// if (is_type_pointer(dst) && is_type_rawptr(src)) {
// return true;
// }
// rawptr <- ^T
if (is_type_rawptr(dst) && is_type_pointer(src)) {
return true;
}
@@ -121,7 +124,7 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
return true;
}
if (is_argument) {
if (true || is_argument) {
// NOTE(bill): Polymorphism for subtyping
if (check_is_assignable_to_using_subtype(type, src)) {
return true;
@@ -224,16 +227,17 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
defer (map_destroy(&entity_map));
isize other_field_index = 0;
Entity *using_index_expr = NULL;
struct Delay {
Entity *e;
AstNode *t;
};
gbArray(Delay) delayed_const; gb_array_init(delayed_const, gb_heap_allocator());
gbArray(Delay) delayed_type; gb_array_init(delayed_type, gb_heap_allocator());
defer (gb_array_free(delayed_const));
defer (gb_array_free(delayed_type));
// TODO(bill): Random declarations with DeclInfo
#if 0
Entity *e;
DeclInfo *d;d
check_entity_decl(c, e, d, NULL);
#endif
gb_for_array(decl_index, decls) {
AstNode *decl = decls[decl_index];
if (decl->kind == AstNode_ConstDecl) {
@@ -252,7 +256,9 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
Token name_token = name->Ident;
Entity *e = make_entity_constant(c->allocator, c->context.scope, name_token, NULL, v);
entities[entity_index++] = e;
check_const_decl(c, e, cd->type, value);
Delay delay = {e, cd->type};
gb_array_append(delayed_const, delay);
}
isize lhs_count = gb_array_count(cd->names);
@@ -288,8 +294,8 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
Token name_token = td->name->Ident;
Entity *e = make_entity_type_name(c->allocator, c->context.scope, name_token, NULL);
add_entity(c, c->context.scope, td->name, e);
check_type_decl(c, e, td->type, NULL, NULL);
Delay delay = {e, td->type};
gb_array_append(delayed_type, delay);
if (name_token.string == "_") {
other_fields[other_field_index++] = e;
@@ -302,10 +308,17 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
map_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);
}
}
}
gb_for_array(i, delayed_type) {
check_const_decl(c, delayed_type[i].e, delayed_type[i].t, NULL);
}
gb_for_array(i, delayed_const) {
check_type_decl(c, delayed_const[i].e, delayed_const[i].t, NULL, NULL);
}
if (node->kind == AstNode_UnionType) {
@@ -1536,18 +1549,15 @@ b32 check_is_castable_to(Checker *c, Operand *operand, Type *y) {
}
// Cast between pointers
if (is_type_pointer(xb)) {
if (is_type_pointer(yb))
if (is_type_pointer(xb) && is_type_pointer(yb)) {
return true;
}
// (u)int <-> pointer
if (is_type_int_or_uint(xb) && !is_type_untyped(xb)) {
if (is_type_pointer(yb))
if (is_type_int_or_uint(xb) && is_type_rawptr(yb)) {
return true;
}
if (is_type_pointer(xb)) {
if (is_type_int_or_uint(yb) && !is_type_untyped(yb))
if (is_type_rawptr(xb) && is_type_int_or_uint(yb)) {
return true;
}
@@ -2961,137 +2971,98 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
GB_ASSERT(proc_type->kind == Type_Proc);
ast_node(ce, CallExpr, call);
isize error_code = 0;
isize param_index = 0;
isize param_count = 0;
b32 variadic = proc_type->Proc.variadic;
b32 vari_expand = (ce->ellipsis.pos.line != 0);
if (proc_type->Proc.params) {
if (proc_type->Proc.params != NULL) {
param_count = proc_type->Proc.params->Tuple.variable_count;
}
if (ce->ellipsis.pos.line != 0) {
if (!variadic) {
error(ce->ellipsis,
"Cannot use `..` in call to a non-variadic procedure: `%.*s`",
LIT(ce->proc->Ident.string));
return;
if (variadic) {
param_count--;
}
}
if (gb_array_count(ce->args) == 0) {
if (variadic && param_count-1 == 0)
return;
if (param_count == 0)
return;
if (vari_expand && !variadic) {
error(ce->ellipsis,
"Cannot use `..` in call to a non-variadic procedure: `%.*s`",
LIT(ce->proc->Ident.string));
return;
}
// TODO(bill): Completely redo this entire code.
// It's from when I used linked lists instead of arrays in the parser
if (gb_array_count(ce->args) == 0 && param_count == 0) {
return;
}
if (gb_array_count(ce->args) > param_count && !variadic) {
isize operand_count = 0;
gbArray(Operand) operands;
gb_array_init_reserve(operands, gb_heap_allocator(), 2*param_count);
defer (gb_array_free(operands));
gb_for_array(i, ce->args) {
Operand o = {};
check_multi_expr(c, &o, ce->args[i]);
if (o.type->kind != Type_Tuple) {
gb_array_append(operands, o);
} else {
auto *tuple = &o.type->Tuple;
if (variadic && i >= param_count) {
error(ast_node_token(ce->args[i]),
"`..` in a variadic procedure cannot be applied to a %td-valued expression", tuple->variable_count);
operand->mode = Addressing_Invalid;
return;
}
for (isize j = 0; j < tuple->variable_count; j++) {
o.type = tuple->variables[j]->type;
gb_array_append(operands, o);
}
}
}
operand_count = gb_array_count(operands);
i32 error_code = 0;
if (operand_count < param_count) {
error_code = -1;
} else if (!variadic && operand_count > param_count) {
error_code = +1;
} else {
Entity **sig_params = proc_type->Proc.params->Tuple.variables;
gb_for_array(arg_index, ce->args) {
check_multi_expr(c, operand, ce->args[arg_index]);
if (operand->mode == Addressing_Invalid) {
param_index++;
continue;
}
if (operand->type->kind != Type_Tuple) {
check_not_tuple(c, operand);
isize index = param_index;
b32 end_variadic = false;
b32 variadic_expand = false;
if (variadic && param_index >= param_count-1) {
index = param_count-1;
end_variadic = true;
if (vari_expand) {
variadic_expand = true;
if (param_index != param_count-1) {
error(ast_node_token(operand->expr),
"`..` in a variadic procedure can only have one variadic argument at the end");
break;
}
}
}
Type *arg_type = sig_params[index]->type;
if (end_variadic && is_type_slice(arg_type)) {
if (variadic_expand) {
check_assignment(c, operand, arg_type, make_string("argument"), true);
} else {
arg_type = base_type(arg_type)->Slice.elem;
check_assignment(c, operand, arg_type, make_string("argument"), true);
}
} else {
check_assignment(c, operand, arg_type, make_string("argument"), true);
}
param_index++;
} else {
auto *tuple = &operand->type->Tuple;
isize i = 0;
for (;
i < tuple->variable_count && (param_index < param_count && !variadic);
i++) {
Entity *e = tuple->variables[i];
operand->type = e->type;
operand->mode = Addressing_Value;
check_not_tuple(c, operand);
isize index = param_index;
b32 end_variadic = false;
if (variadic && param_index >= param_count-1) {
index = param_count-1;
end_variadic = true;
if (vari_expand) {
error(ast_node_token(operand->expr),
"`..` in a variadic procedure cannot be applied to a %td-valued expression", tuple->variable_count);
goto end;
}
}
Type *arg_type = sig_params[index]->type;
if (end_variadic && is_type_slice(arg_type)) {
arg_type = base_type(arg_type)->Slice.elem;
}
check_assignment(c, operand, arg_type, make_string("argument"), true);
param_index++;
}
end:
if (i < tuple->variable_count && param_index == param_count) {
error_code = +1;
break;
}
}
if (!variadic && param_index >= param_count)
break;
}
if ((!variadic && param_index < param_count) ||
(variadic && param_index < param_count-1)) {
error_code = -1;
}
}
if (error_code != 0) {
char *err_fmt = "";
char *err_fmt = "Too many arguments for `%s`, expected %td arguments";
if (error_code < 0) {
err_fmt = "Too few arguments for `%s`, expected %td arguments";
} else {
err_fmt = "Too many arguments for `%s`, expected %td arguments";
}
gbString proc_str = expr_to_string(ce->proc);
error(ast_node_token(call), err_fmt, proc_str, param_count);
gb_string_free(proc_str);
operand->mode = Addressing_Invalid;
}
GB_ASSERT(proc_type->Proc.params != NULL);
Entity **sig_params = proc_type->Proc.params->Tuple.variables;
for (isize i = 0; i < param_count; i++) {
Type *arg_type = sig_params[i]->type;
check_assignment(c, &operands[i], arg_type, make_string("argument"), true);
}
if (variadic) {
b32 variadic_expand = false;
Type *slice = sig_params[param_count]->type;
Type *elem = base_type(slice)->Slice.elem;
Type *t = elem;
for (isize i = param_count; i < operand_count; i++) {
Operand *o = &operands[i];
if (vari_expand) {
variadic_expand = true;
t = slice;
if (i != param_count) {
error(ast_node_token(o->expr),
"`..` in a variadic procedure can only have one variadic argument at the end");
break;
}
}
check_assignment(c, o, t, make_string("argument"), true);
}
}
}

View File

@@ -11,8 +11,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags);
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d);
void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
// TODO(bill): Allow declaration (expect variable) in any order
// even within a procedure
struct Delay {
Entity *e;
DeclInfo *d;
@@ -57,7 +55,6 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
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;
add_entity(c, c->context.scope, td->name, e);
DeclInfo *d = make_declaration_info(c->allocator, e->scope);
d->type_expr = td->type;
@@ -339,7 +336,7 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
// TODO(bill): Do not use heap allocation here if I can help it
gbArray(Operand) operands;
gb_array_init(operands, gb_heap_allocator());
gb_array_init_reserve(operands, gb_heap_allocator(), 2*lhs_count);
defer (gb_array_free(operands));
gb_for_array(i, inits) {

View File

@@ -1799,7 +1799,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
// NOTE(bill): This has to be done beofre `Pointer <-> Pointer` as it's
// subtype polymorphism casting
if (is_argument) {
if (true || is_argument) {
Type *sb = base_type(type_deref(src));
b32 src_is_ptr = src != sb;
if (is_type_struct(sb)) {
@@ -1924,8 +1924,9 @@ ssaValue *ssa_emit_transmute(ssaProcedure *proc, ssaValue *value, Type *t) {
Type *src = base_type(src_type);
Type *dst = base_type(t);
if (are_types_identical(t, src_type))
if (are_types_identical(t, src_type)) {
return value;
}
i64 sz = type_size_of(proc->module->sizes, proc->module->allocator, src);
i64 dz = type_size_of(proc->module->sizes, proc->module->allocator, dst);
@@ -1950,8 +1951,6 @@ ssaValue *ssa_emit_down_cast(ssaProcedure *proc, ssaValue *value, Type *t) {
Type *t_u8_ptr = make_type_pointer(allocator, t_u8);
ssaValue *bytes = ssa_emit_conv(proc, value, t_u8_ptr);
// IMPORTANT TODO(bill): THIS ONLY DOES ONE LAYER DEEP!!! FUCKING HELL THIS IS NOT WHAT I SIGNED UP FOR!
i64 offset_ = type_offset_of_from_selection(proc->module->sizes, allocator, type_deref(t), sel);
ssaValue *offset = ssa_make_const_int(allocator, -offset_);
ssaValue *head = ssa_emit_ptr_offset(proc, bytes, offset);