mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-13 14:51:26 -07:00
This commit is contained in:
+35
-12
@@ -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)) {
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
irValue *slice_size = ir_emit_arith(proc, Token_Mul, elem_size, count, 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, 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));
|
||||
|
||||
+5
-6
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-4
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user