#define _POSIX_C_SOURCE 200809L #include "types.h" #include #include #include static RavaType_t _type_void = { RAVA_TYPE_VOID, "void", { .array = { NULL, 0 } } }; static RavaType_t _type_boolean = { RAVA_TYPE_BOOLEAN, "boolean", { .array = { NULL, 0 } } }; static RavaType_t _type_byte = { RAVA_TYPE_BYTE, "byte", { .array = { NULL, 0 } } }; static RavaType_t _type_short = { RAVA_TYPE_SHORT, "short", { .array = { NULL, 0 } } }; static RavaType_t _type_int = { RAVA_TYPE_INT, "int", { .array = { NULL, 0 } } }; static RavaType_t _type_long = { RAVA_TYPE_LONG, "long", { .array = { NULL, 0 } } }; static RavaType_t _type_char = { RAVA_TYPE_CHAR, "char", { .array = { NULL, 0 } } }; static RavaType_t _type_float = { RAVA_TYPE_FLOAT, "float", { .array = { NULL, 0 } } }; static RavaType_t _type_double = { RAVA_TYPE_DOUBLE, "double", { .array = { NULL, 0 } } }; static RavaType_t _type_null = { RAVA_TYPE_NULL, "null", { .array = { NULL, 0 } } }; static RavaType_t _type_string = { RAVA_TYPE_CLASS, "String", { .class_type = { "String" } } }; static inline bool _is_pooled_type(RavaType_t *type) { return type == &_type_void || type == &_type_boolean || type == &_type_byte || type == &_type_short || type == &_type_int || type == &_type_long || type == &_type_char || type == &_type_float || type == &_type_double || type == &_type_null || type == &_type_string; } RavaType_t* rava_type_create_primitive(RavaTypeKind_e kind) { switch (kind) { case RAVA_TYPE_VOID: return &_type_void; case RAVA_TYPE_BOOLEAN: return &_type_boolean; case RAVA_TYPE_BYTE: return &_type_byte; case RAVA_TYPE_SHORT: return &_type_short; case RAVA_TYPE_INT: return &_type_int; case RAVA_TYPE_LONG: return &_type_long; case RAVA_TYPE_CHAR: return &_type_char; case RAVA_TYPE_FLOAT: return &_type_float; case RAVA_TYPE_DOUBLE: return &_type_double; case RAVA_TYPE_NULL: return &_type_null; default: { RavaType_t *type = calloc(1, sizeof(RavaType_t)); type->kind = kind; type->name = strdup("unknown"); return type; } } } RavaType_t* rava_type_create_class(const char *class_name) { RavaType_t *type = calloc(1, sizeof(RavaType_t)); type->kind = RAVA_TYPE_CLASS; type->name = strdup(class_name); type->data.class_type.class_name = strdup(class_name); return type; } RavaType_t* rava_type_create_array(RavaType_t *element_type, int dimensions) { RavaType_t *type = calloc(1, sizeof(RavaType_t)); type->kind = RAVA_TYPE_ARRAY; type->data.array.element_type = element_type; type->data.array.dimensions = dimensions; char buffer[256]; snprintf(buffer, sizeof(buffer), "%s", rava_type_to_string(element_type)); for (int i = 0; i < dimensions; i++) { strcat(buffer, "[]"); } type->name = strdup(buffer); return type; } void rava_type_destroy(RavaType_t *type) { if (!type || _is_pooled_type(type)) return; free(type->name); if (type->kind == RAVA_TYPE_ARRAY) { rava_type_destroy(type->data.array.element_type); } else if (type->kind == RAVA_TYPE_CLASS) { free(type->data.class_type.class_name); } free(type); } RavaType_t* rava_type_from_name(const char *type_name) { if (strcmp(type_name, "void") == 0) return rava_type_create_primitive(RAVA_TYPE_VOID); if (strcmp(type_name, "boolean") == 0) return rava_type_create_primitive(RAVA_TYPE_BOOLEAN); if (strcmp(type_name, "byte") == 0) return rava_type_create_primitive(RAVA_TYPE_BYTE); if (strcmp(type_name, "short") == 0) return rava_type_create_primitive(RAVA_TYPE_SHORT); if (strcmp(type_name, "int") == 0) return rava_type_create_primitive(RAVA_TYPE_INT); if (strcmp(type_name, "long") == 0) return rava_type_create_primitive(RAVA_TYPE_LONG); if (strcmp(type_name, "char") == 0) return rava_type_create_primitive(RAVA_TYPE_CHAR); if (strcmp(type_name, "float") == 0) return rava_type_create_primitive(RAVA_TYPE_FLOAT); if (strcmp(type_name, "double") == 0) return rava_type_create_primitive(RAVA_TYPE_DOUBLE); return rava_type_create_class(type_name); } bool rava_type_is_primitive(RavaType_t *type) { return type->kind >= RAVA_TYPE_VOID && type->kind <= RAVA_TYPE_DOUBLE; } bool rava_type_is_numeric(RavaType_t *type) { return type->kind >= RAVA_TYPE_BYTE && type->kind <= RAVA_TYPE_DOUBLE; } bool rava_type_is_integral(RavaType_t *type) { return type->kind >= RAVA_TYPE_BYTE && type->kind <= RAVA_TYPE_CHAR; } bool rava_type_is_floating(RavaType_t *type) { return type->kind == RAVA_TYPE_FLOAT || type->kind == RAVA_TYPE_DOUBLE; } bool rava_type_is_reference(RavaType_t *type) { return type->kind == RAVA_TYPE_CLASS || type->kind == RAVA_TYPE_ARRAY || type->kind == RAVA_TYPE_NULL; } bool rava_type_equals(RavaType_t *a, RavaType_t *b) { if (!a || !b) return false; if (a->kind != b->kind) return false; if (a->kind == RAVA_TYPE_ARRAY) { return a->data.array.dimensions == b->data.array.dimensions && rava_type_equals(a->data.array.element_type, b->data.array.element_type); } if (a->kind == RAVA_TYPE_CLASS) { return strcmp(a->data.class_type.class_name, b->data.class_type.class_name) == 0; } return true; } bool rava_type_is_assignable_to(RavaType_t *from, RavaType_t *to) { if (!from || !to) return false; if (rava_type_equals(from, to)) return true; if (from->kind == RAVA_TYPE_NULL && rava_type_is_reference(to)) { return true; } if (rava_type_is_numeric(from) && rava_type_is_numeric(to)) { int from_rank = from->kind - RAVA_TYPE_BYTE; int to_rank = to->kind - RAVA_TYPE_BYTE; return from_rank <= to_rank; } return false; } bool rava_type_is_castable_to(RavaType_t *from, RavaType_t *to) { if (rava_type_is_assignable_to(from, to)) return true; if (rava_type_is_numeric(from) && rava_type_is_numeric(to)) { return true; } if (rava_type_is_reference(from) && rava_type_is_reference(to)) { return true; } return false; } static bool _is_string_type(RavaType_t *type) { return type->kind == RAVA_TYPE_CLASS && type->data.class_type.class_name && strcmp(type->data.class_type.class_name, "String") == 0; } RavaType_t* rava_type_binary_result(RavaType_t *left, RavaType_t *right) { if (!left || !right) return NULL; if (_is_string_type(left) || _is_string_type(right)) { return &_type_string; } if (!rava_type_is_numeric(left) || !rava_type_is_numeric(right)) { return NULL; } if (left->kind == RAVA_TYPE_DOUBLE || right->kind == RAVA_TYPE_DOUBLE) { return &_type_double; } if (left->kind == RAVA_TYPE_FLOAT || right->kind == RAVA_TYPE_FLOAT) { return &_type_float; } if (left->kind == RAVA_TYPE_LONG || right->kind == RAVA_TYPE_LONG) { return &_type_long; } return &_type_int; } RavaType_t* rava_type_unary_result(RavaType_t *operand) { if (!operand) return NULL; if (!rava_type_is_numeric(operand)) { return NULL; } if (operand->kind == RAVA_TYPE_BYTE || operand->kind == RAVA_TYPE_SHORT || operand->kind == RAVA_TYPE_CHAR) { return &_type_int; } return rava_type_create_primitive(operand->kind); } const char* rava_type_to_string(RavaType_t *type) { if (!type) return "null"; return type->name; }