diff options
| author | Zac Pierson <zacpiersonhehe@gmail.com> | 2017-03-02 15:41:19 -0600 |
|---|---|---|
| committer | Zac Pierson <zacpiersonhehe@gmail.com> | 2017-03-02 15:41:19 -0600 |
| commit | d890731716ea96fd69d7543c7d7225702cbd7268 (patch) | |
| tree | 2fb1a025fc214ccc55a6515adb276c3bc4ac7a77 /src | |
| parent | 231ea8b0264e8b6d47278f01fb7c31b8562c2bbb (diff) | |
| parent | 9e8c9be1ea825c2b5c66e62724519ae9ab8ab8f6 (diff) | |
Merge https://github.com/gingerBill/Odin
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_expr.c | 47 | ||||
| -rw-r--r-- | src/checker.c | 2 | ||||
| -rw-r--r-- | src/ir.c | 21 | ||||
| -rw-r--r-- | src/ir_print.c | 11 | ||||
| -rw-r--r-- | src/types.c | 5 |
5 files changed, 58 insertions, 28 deletions
diff --git a/src/check_expr.c b/src/check_expr.c index 0e166ef1a..7e273fba4 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -2918,9 +2918,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id err = "Too many"; } - if (err) { + if (err != NULL) { gbString expr = expr_to_string(ce->proc); - error(ce->close, "`%s` arguments for `%s`, expected %td, got %td", + error(ce->close, "%s arguments for `%s`, expected %td, got %td", err, expr, bp->arg_count, ce->args.count); gb_string_free(expr); @@ -2962,6 +2962,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } break; case BuiltinProc_new_slice: { // new_slice :: proc(Type, len: int) -> []Type + // new_slice :: proc(Type, len, cap: int) -> []Type Operand op = {0}; check_expr_or_type(c, &op, ce->args.e[0]); Type *type = op.type; @@ -2970,15 +2971,27 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id return false; } - check_expr(c, &op, ce->args.e[1]); - if (op.mode == Addressing_Invalid) { - return false; - } - if (!is_type_integer(op.type)) { - gbString type_str = type_to_string(op.type); - error_node(call, "Length for `new_slice` must be an integer, got `%s`", type_str); - gb_string_free(type_str); - return false; + isize arg_count = ce->args.count; + if (arg_count < 2 || 3 < arg_count) { + error_node(ce->args.e[0], "`new_slice` expects 2 or 3 arguments, found %td", arg_count); + // NOTE(bill): Return the correct type to reduce errors + } else { + // If any are constant + i64 sizes[2] = {0}; + isize size_count = 0; + for (isize i = 1; i < arg_count; i++) { + i64 val = 0; + bool ok = check_index_value(c, ce->args.e[i], -1, &val); + if (ok && val >= 0) { + GB_ASSERT(size_count < gb_count_of(sizes)); + sizes[size_count++] = val; + } + } + + if (size_count == 2 && sizes[0] > sizes[1]) { + error_node(ce->args.e[1], "`new_slice` count and capacity are swapped"); + // No need quit + } } operand->mode = Addressing_Value; @@ -3060,7 +3073,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id // append :: proc([dynamic]Type, item: ..Type) // append :: proc([]Type, item: ..Type) Type *type = operand->type; - type = base_type(type); + bool is_pointer = is_type_pointer(type); + type = base_type(type_deref(type)); if (!is_type_dynamic_array(type) && !is_type_slice(type)) { gbString str = type_to_string(type); error_node(operand->expr, "Expected a slice or dynamic array, got `%s`", str); @@ -3068,6 +3082,15 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id return false; } + bool is_addressable = operand->mode == Addressing_Variable; + if (is_pointer) { + is_addressable = true; + } + if (!is_addressable) { + error_node(operand->expr, "`append` can only operate on addressable values"); + return false; + } + Type *elem = NULL; Type *slice_elem = NULL; if (is_type_dynamic_array(type)) { diff --git a/src/checker.c b/src/checker.c index 62a243bb6..ecb0f033b 100644 --- a/src/checker.c +++ b/src/checker.c @@ -68,7 +68,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = { {STR_LIT(""), 0, false, Expr_Stmt}, {STR_LIT("new"), 1, false, Expr_Expr}, - {STR_LIT("new_slice"), 2, false, Expr_Expr}, + {STR_LIT("new_slice"), 2, true, Expr_Expr}, {STR_LIT("free"), 1, false, Expr_Stmt}, {STR_LIT("reserve"), 2, false, Expr_Stmt}, @@ -3168,7 +3168,8 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv case BuiltinProc_new_slice: { ir_emit_comment(proc, str_lit("new_slice")); - // new_slice :: proc(Type, len: int) -> ^Type + // new_slice :: proc(Type, len: int) -> []Type + // new_slice :: proc(Type, len, cap: int) -> []Type gbAllocator allocator = proc->module->allocator; Type *type = type_of_expr(proc->module->info, ce->args.e[0]); @@ -3182,10 +3183,15 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv irValue *elem_align = ir_make_const_int(allocator, a); irValue *count = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[1]), t_int); + irValue *capacity = count; - ir_emit_slice_bounds_check(proc, ast_node_token(ce->args.e[1]), v_zero, count, count, false); + if (ce->args.count == 3) { + capacity = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[2]), t_int); + } + + ir_emit_slice_bounds_check(proc, ast_node_token(ce->args.e[1]), v_zero, count, capacity, false); - irValue *slice_size = ir_emit_arith(proc, Token_Mul, elem_size, count, t_int); + irValue *slice_size = ir_emit_arith(proc, Token_Mul, elem_size, capacity, t_int); irValue **args = gb_alloc_array(allocator, irValue *, 2); args[0] = slice_size; @@ -3195,7 +3201,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv irValue *ptr = ir_emit_conv(proc, call, ptr_type); irValue *slice = ir_add_local_generated(proc, slice_type); - ir_fill_slice(proc, slice, ptr, count, count); + ir_fill_slice(proc, slice, ptr, count, capacity); return ir_emit_load(proc, slice); } break; @@ -3330,7 +3336,12 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv ir_emit_comment(proc, str_lit("append")); gbAllocator a = proc->module->allocator; - irValue *array_ptr = ir_build_addr(proc, ce->args.e[0]).addr; + Type *value_type = type_of_expr(proc->module->info, ce->args.e[0]); + irAddr array_addr = ir_build_addr(proc, ce->args.e[0]); + irValue *array_ptr = array_addr.addr; + if (is_type_pointer(value_type)) { + array_ptr = ir_addr_load(proc, array_addr); + } Type *type = ir_type(array_ptr); GB_ASSERT(is_type_pointer(type)); type = base_type(type_deref(type)); diff --git a/src/ir_print.c b/src/ir_print.c index 9bc7e5f41..cca26b925 100644 --- a/src/ir_print.c +++ b/src/ir_print.c @@ -664,6 +664,11 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { ir_fprintf(f, "\t"); switch (instr->kind) { + default: { + GB_PANIC("<unknown instr> %d\n", instr->kind); + ir_fprintf(f, "; <unknown instr> %d\n", instr->kind); + } break; + case irInstr_StartupRuntime: { ir_fprintf(f, "call void "); ir_print_encoded_global(f, str_lit(IR_STARTUP_RUNTIME_PROC_NAME), false); @@ -1281,12 +1286,6 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { ir_fprintf(f, "\n"); */ } break; - - - default: { - GB_PANIC("<unknown instr> %d\n", instr->kind); - ir_fprintf(f, "; <unknown instr> %d\n", instr->kind); - } break; } } diff --git a/src/types.c b/src/types.c index 0142fa227..362e949fb 100644 --- a/src/types.c +++ b/src/types.c @@ -1342,9 +1342,6 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n } } - if (type->kind != Type_Record) { - return sel; - } if (is_type) { if (type->kind == Type_Record) { if (type->Record.names != NULL && @@ -1395,7 +1392,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n } } } - } else { + } else if (type->kind == Type_Record) { for (isize i = 0; i < type->Record.field_count; i++) { Entity *f = type->Record.fields[i]; if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) { |