mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-19 01:18:22 +00:00
expand_to_tuple
This commit is contained in:
@@ -1516,6 +1516,7 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
|
||||
type->Proc.result_count = result_count;
|
||||
type->Proc.variadic = variadic;
|
||||
type->Proc.calling_convention = pt->calling_convention;
|
||||
type->Proc.is_generic = pt->generic;
|
||||
|
||||
if (param_count > 0) {
|
||||
Entity *end = params->Tuple.variables[param_count-1];
|
||||
@@ -1530,18 +1531,19 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
|
||||
type->Proc.c_vararg = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_generic = false;
|
||||
for (isize i = 0; i < param_count; i++) {
|
||||
Entity *e = params->Tuple.variables[i];
|
||||
if (e->type->kind == Type_Generic) {
|
||||
is_generic = true;
|
||||
}
|
||||
}
|
||||
type->Proc.is_generic = is_generic;
|
||||
}
|
||||
|
||||
|
||||
bool is_generic = false;
|
||||
for (isize i = 0; i < param_count; i++) {
|
||||
Entity *e = params->Tuple.variables[i];
|
||||
if (e->type->kind == Type_Generic) {
|
||||
is_generic = true;
|
||||
}
|
||||
}
|
||||
GB_ASSERT(type->Proc.is_generic == is_generic);
|
||||
|
||||
|
||||
type->Proc.abi_compat_params = gb_alloc_array(c->allocator, Type *, param_count);
|
||||
for (isize i = 0; i < param_count; i++) {
|
||||
Type *original_type = type->Proc.params->Tuple.variables[i]->type;
|
||||
@@ -4490,6 +4492,29 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
operand->mode = Addressing_Value;
|
||||
} break;
|
||||
|
||||
case BuiltinProc_expand_to_tuple: {
|
||||
Type *type = base_type(operand->type);
|
||||
if (!is_type_struct(type) &
|
||||
!is_type_union(type)) {
|
||||
gbString type_str = type_to_string(operand->type);
|
||||
error(call, "Expected a struct or union type, got `%s`", type_str);
|
||||
gb_string_free(type_str);
|
||||
return false;
|
||||
}
|
||||
gbAllocator a = c->allocator;
|
||||
|
||||
Type *tuple = make_type_tuple(a);
|
||||
i32 variable_count = type->Record.field_count;
|
||||
tuple->Tuple.variables = gb_alloc_array(a, Entity *, variable_count);
|
||||
tuple->Tuple.variable_count = variable_count;
|
||||
|
||||
// TODO(bill): Should I copy each of the entities or is this good enough?
|
||||
gb_memcopy_array(tuple->Tuple.variables, type->Record.fields, variable_count);
|
||||
|
||||
operand->type = tuple;
|
||||
operand->mode = Addressing_Value;
|
||||
} break;
|
||||
|
||||
case BuiltinProc_min: {
|
||||
// proc min(a, b: ordered) -> ordered
|
||||
Type *type = base_type(operand->type);
|
||||
|
||||
@@ -56,6 +56,8 @@ enum BuiltinProcId {
|
||||
BuiltinProc_slice_ptr,
|
||||
BuiltinProc_slice_to_bytes,
|
||||
|
||||
BuiltinProc_expand_to_tuple,
|
||||
|
||||
BuiltinProc_min,
|
||||
BuiltinProc_max,
|
||||
BuiltinProc_abs,
|
||||
@@ -99,8 +101,10 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
||||
{STR_LIT("imag"), 1, false, Expr_Expr},
|
||||
{STR_LIT("conj"), 1, false, Expr_Expr},
|
||||
|
||||
{STR_LIT("slice_ptr"), 2, true, Expr_Expr},
|
||||
{STR_LIT("slice_to_bytes"), 1, false, Expr_Stmt},
|
||||
{STR_LIT("slice_ptr"), 2, true, Expr_Expr},
|
||||
{STR_LIT("slice_to_bytes"), 1, false, Expr_Stmt},
|
||||
|
||||
{STR_LIT("expand_to_tuple"), 1, false, Expr_Expr},
|
||||
|
||||
{STR_LIT("min"), 2, false, Expr_Expr},
|
||||
{STR_LIT("max"), 2, false, Expr_Expr},
|
||||
@@ -328,6 +332,15 @@ void scope_lookup_parent_entity (Scope *s, String name, Scope **scope_, Entit
|
||||
Entity *scope_insert_entity (Scope *s, Entity *entity);
|
||||
|
||||
|
||||
ExprInfo *check_get_expr_info(CheckerInfo *i, AstNode *expr);
|
||||
void check_set_expr_info(CheckerInfo *i, AstNode *expr, ExprInfo info);
|
||||
void check_remove_expr_info(CheckerInfo *i, AstNode *expr);
|
||||
void add_untyped(CheckerInfo *i, AstNode *expression, bool lhs, AddressingMode mode, Type *basic_type, ExactValue value);
|
||||
void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode, Type *type, ExactValue value);
|
||||
void add_entity_use(Checker *c, AstNode *identifier, Entity *entity);
|
||||
void add_implicit_entity(Checker *c, AstNode *node, Entity *e);
|
||||
void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclInfo *d);
|
||||
void add_implicit_entity(Checker *c, AstNode *node, Entity *e);
|
||||
|
||||
|
||||
void init_declaration_info(DeclInfo *d, Scope *scope, DeclInfo *parent) {
|
||||
|
||||
17
src/ir.cpp
17
src/ir.cpp
@@ -4283,6 +4283,23 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
return ir_emit_load(proc, slice);
|
||||
} break;
|
||||
|
||||
case BuiltinProc_expand_to_tuple: {
|
||||
ir_emit_comment(proc, str_lit("expand_to_tuple"));
|
||||
irValue *s = ir_build_expr(proc, ce->args[0]);
|
||||
Type *t = base_type(ir_type(s));
|
||||
|
||||
GB_ASSERT(t->kind == Type_Record);
|
||||
GB_ASSERT(is_type_tuple(tv.type));
|
||||
|
||||
irValue *tuple = ir_add_local_generated(proc, tv.type);
|
||||
for (isize i = 0; i < t->Record.field_count; i++) {
|
||||
irValue *f = ir_emit_struct_ev(proc, s, i);
|
||||
irValue *ep = ir_emit_struct_ep(proc, tuple, i);
|
||||
ir_emit_store(proc, ep, f);
|
||||
}
|
||||
return ir_emit_load(proc, tuple);
|
||||
} break;
|
||||
|
||||
case BuiltinProc_min: {
|
||||
ir_emit_comment(proc, str_lit("min"));
|
||||
Type *t = type_of_expr(proc->module->info, expr);
|
||||
|
||||
@@ -393,6 +393,7 @@ AST_NODE_KIND(_TypeBegin, "", i32) \
|
||||
AstNode *results; \
|
||||
u64 tags; \
|
||||
ProcCallingConvention calling_convention; \
|
||||
bool generic; \
|
||||
}) \
|
||||
AST_NODE_KIND(PointerType, "pointer type", struct { \
|
||||
Token token; \
|
||||
@@ -1370,16 +1371,18 @@ AstNode *ast_helper_type(AstFile *f, Token token) {
|
||||
}
|
||||
|
||||
|
||||
AstNode *ast_proc_type(AstFile *f, Token token, AstNode *params, AstNode *results, u64 tags, ProcCallingConvention calling_convention) {
|
||||
AstNode *ast_proc_type(AstFile *f, Token token, AstNode *params, AstNode *results, u64 tags, ProcCallingConvention calling_convention, bool generic) {
|
||||
AstNode *result = make_ast_node(f, AstNode_ProcType);
|
||||
result->ProcType.token = token;
|
||||
result->ProcType.params = params;
|
||||
result->ProcType.results = results;
|
||||
result->ProcType.tags = tags;
|
||||
result->ProcType.calling_convention = calling_convention;
|
||||
result->ProcType.generic = generic;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AstNode *ast_pointer_type(AstFile *f, Token token, AstNode *type) {
|
||||
AstNode *result = make_ast_node(f, AstNode_PointerType);
|
||||
result->PointerType.token = token;
|
||||
@@ -3214,7 +3217,20 @@ AstNode *parse_proc_type(AstFile *f, Token proc_token, String *link_name_) {
|
||||
|
||||
if (link_name_) *link_name_ = link_name;
|
||||
|
||||
return ast_proc_type(f, proc_token, params, results, tags, cc);
|
||||
bool is_generic = false;
|
||||
|
||||
for_array(i, params->FieldList.list) {
|
||||
AstNode *param = params->FieldList.list[i];
|
||||
ast_node(f, Field, param);
|
||||
if (f->type != NULL &&
|
||||
f->type->kind == AstNode_HelperType) {
|
||||
is_generic = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ast_proc_type(f, proc_token, params, results, tags, cc, is_generic);
|
||||
}
|
||||
|
||||
AstNode *parse_var_type(AstFile *f, bool allow_ellipsis, bool allow_type_token) {
|
||||
|
||||
Reference in New Issue
Block a user