From 51e50d3e318ce2588ce2d27c2af7ef6f11a0f02b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 1 Jul 2020 22:35:38 +0100 Subject: [PATCH] Add `intrinsics.type_proc_parameter_type`; Add `intrinsics.type_proc_return_type` --- core/intrinsics/intrinsics.odin | 10 ++- src/check_expr.cpp | 124 +++++++++++++++++++++++++++++++- src/checker_builtin_procs.hpp | 6 ++ 3 files changed, 135 insertions(+), 5 deletions(-) diff --git a/core/intrinsics/intrinsics.odin b/core/intrinsics/intrinsics.odin index cb3df0c16..45245960b 100644 --- a/core/intrinsics/intrinsics.odin +++ b/core/intrinsics/intrinsics.odin @@ -125,9 +125,15 @@ type_is_bit_field_value :: proc($T: typeid) -> bool --- type_is_bit_set :: proc($T: typeid) -> bool --- type_is_simd_vector :: proc($T: typeid) -> bool --- -type_is_specialization_of :: proc($T, $S: typeid) -> bool --- - type_has_nil :: proc($T: typeid) -> bool --- +type_is_specialization_of :: proc($T, $S: typeid) -> bool --- + type_proc_parameter_count :: proc($T: typeid) -> int where type_is_proc(T) --- type_proc_return_count :: proc($T: typeid) -> int where type_is_proc(T) --- + +type_proc_parameter_type :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) --- +type_proc_return_type :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) --- + +type_polymorphic_record_parameter_count :: proc($T: typeid) -> typeid --- +type_polymorphic_record_parameter_value :: proc($T: typeid, index: int) -> $V --- diff --git a/src/check_expr.cpp b/src/check_expr.cpp index a2b7bb057..eda2b7e95 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -5692,6 +5692,124 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 operand->type = t_untyped_integer; break; + case BuiltinProc_type_proc_parameter_type: + if (operand->mode != Addressing_Type || !is_type_proc(operand->type)) { + error(operand->expr, "Expected a procedure type for '%.*s'", LIT(builtin_name)); + return false; + } else { + if (is_type_polymorphic(operand->type)) { + error(operand->expr, "Expected a non-polymorphic procedure type for '%.*s'", LIT(builtin_name)); + return false; + } + + Operand op = {}; + check_expr(c, &op, ce->args[1]); + if (op.mode != Addressing_Constant && !is_type_integer(op.type)) { + error(op.expr, "Expected a constant integer for the index of procedure parameter value"); + return false; + } + + i64 index = exact_value_to_i64(op.value); + if (index < 0) { + error(op.expr, "Expected a non-negative integer for the index of procedure parameter value, got %lld", cast(long long)index); + return false; + } + + Entity *param = nullptr; + i64 count = 0; + + Type *bt = base_type(operand->type); + if (bt->kind == Type_Proc) { + count = bt->Proc.param_count; + if (index < count) { + param = bt->Proc.params->Tuple.variables[index]; + } + } + + if (index >= count) { + error(op.expr, "Index of procedure parameter value out of bounds, expected 0..<%lld, got %lld", cast(long long)count, cast(long long)index); + return false; + } + GB_ASSERT(param != nullptr); + switch (param->kind) { + case Entity_Constant: + operand->mode = Addressing_Constant; + operand->type = param->type; + operand->value = param->Constant.value; + break; + case Entity_TypeName: + case Entity_Variable: + operand->mode = Addressing_Type; + operand->type = param->type; + break; + default: + GB_PANIC("Unhandled procedure entity type %d", param->kind); + break; + } + + } + + break; + + case BuiltinProc_type_proc_return_type: + if (operand->mode != Addressing_Type || !is_type_proc(operand->type)) { + error(operand->expr, "Expected a procedure type for '%.*s'", LIT(builtin_name)); + return false; + } else { + if (is_type_polymorphic(operand->type)) { + error(operand->expr, "Expected a non-polymorphic procedure type for '%.*s'", LIT(builtin_name)); + return false; + } + + Operand op = {}; + check_expr(c, &op, ce->args[1]); + if (op.mode != Addressing_Constant && !is_type_integer(op.type)) { + error(op.expr, "Expected a constant integer for the index of procedure parameter value"); + return false; + } + + i64 index = exact_value_to_i64(op.value); + if (index < 0) { + error(op.expr, "Expected a non-negative integer for the index of procedure parameter value, got %lld", cast(long long)index); + return false; + } + + Entity *param = nullptr; + i64 count = 0; + + Type *bt = base_type(operand->type); + if (bt->kind == Type_Proc) { + count = bt->Proc.result_count; + if (index < count) { + param = bt->Proc.results->Tuple.variables[index]; + } + } + + if (index >= count) { + error(op.expr, "Index of procedure parameter value out of bounds, expected 0..<%lld, got %lld", cast(long long)count, cast(long long)index); + return false; + } + GB_ASSERT(param != nullptr); + switch (param->kind) { + case Entity_Constant: + operand->mode = Addressing_Constant; + operand->type = param->type; + operand->value = param->Constant.value; + break; + case Entity_TypeName: + case Entity_Variable: + operand->mode = Addressing_Type; + operand->type = param->type; + break; + default: + GB_PANIC("Unhandled procedure entity type %d", param->kind); + break; + } + + } + + break; + case BuiltinProc_type_polymorphic_record_parameter_count: operand->value = exact_value_i64(0); if (operand->mode != Addressing_Type) { @@ -5724,13 +5842,13 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 Operand op = {}; check_expr(c, &op, ce->args[1]); if (op.mode != Addressing_Constant && !is_type_integer(op.type)) { - error(op.expr, "Execpted a constant integer for the index of record parameter value"); + error(op.expr, "Expected a constant integer for the index of record parameter value"); return false; } i64 index = exact_value_to_i64(op.value); if (index < 0) { - error(op.expr, "Execpted a non-negative integer for the index of record parameter value, got %lld", cast(long long)index); + error(op.expr, "Expected a non-negative integer for the index of record parameter value, got %lld", cast(long long)index); return false; } @@ -5773,7 +5891,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 operand->type = param->type; break; default: - GB_PANIC("Unhandle polymorphic record type"); + GB_PANIC("Unhandled polymorphic record type"); break; } diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 074e287d1..ea6ba82f9 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -172,6 +172,9 @@ BuiltinProc__type_simple_boolean_end, BuiltinProc_type_proc_parameter_count, BuiltinProc_type_proc_return_count, + BuiltinProc_type_proc_parameter_type, + BuiltinProc_type_proc_return_type, + BuiltinProc_type_polymorphic_record_parameter_count, BuiltinProc_type_polymorphic_record_parameter_value, @@ -348,6 +351,9 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_proc_parameter_count"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_proc_return_count"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_proc_parameter_type"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_proc_return_type"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_polymorphic_record_parameter_count"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_polymorphic_record_parameter_value"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},