From fee504636f9cd7633217e1877ee1b99e555bba63 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Mon, 3 Oct 2016 23:28:37 +0100 Subject: [PATCH] Code clean up of call arguments --- code/demo.odin | 9 +- src/checker/expr.cpp | 227 +++++++++++++++++++------------------------ src/checker/stmt.cpp | 5 +- src/codegen/ssa.cpp | 7 +- 4 files changed, 104 insertions(+), 144 deletions(-) diff --git a/code/demo.odin b/code/demo.odin index 17d3bf52a..ff80f434d 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -5,12 +5,5 @@ #import "game.odin" main :: proc() { - Vector3 :: struct { - x, y, z: f32 - } - Entity :: struct { - guid: u64 - position: Vector3 - } - + fmt.println("Hellope") } diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index 24c61fb14..bf17cf2e3 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -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); + } + } } diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index 88fb32b4c..0ca457c9a 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -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) { diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index e8aa3bebf..b355f2acc 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -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);