nctref/src/types.c
2024-12-14 18:13:33 +02:00

178 lines
3.4 KiB
C

#include"types.h"
#include"utils.h"
#include<stdlib.h>
#include<string.h>
#include<stdint.h>
#include"ntc.h"
Type TYPE_ERROR = {.type = TYPE_TYPE_ERROR};
static TypePrimitive *primitiveDatabase[128];
Type *primitive_parse(const char *src) {
size_t hash = djb2(src) % 128;
for(TypePrimitive *t = primitiveDatabase[hash]; t; t = t->next) {
if(!strcmp(src, t->src)) {
return (Type*) t;
}
}
TypePrimitive *ret = malloc(sizeof(*ret));
ret->type = TYPE_TYPE_PRIMITIVE;
ret->src = strdup(src);
if(*src == 'n') {
src++;
ret->isNative = 1;
} else {
ret->isNative = 0;
}
if(*src == 'u') {
src++;
ret->isUnsigned = 1;
} else if(*src == 's') {
src++;
ret->isUnsigned = 0;
} else {
free(ret);
return NULL;
}
if(*src == 'm') {
src++;
ret->isMinimum = 1;
} else {
ret->isMinimum = 0;
}
if(*src == 'f') {
src++;
ret->isFloat = 1;
} else {
ret->isFloat = 0;
}
ret->width = strtol(src, (char**) &src, 10);
if(*src == 'b') {
src++;
ret->base = strtol(src, (char**) &src, 10);
} else {
ret->base = 2;
}
if(*src == 'v') {
src++;
ret->vector = strtol(src, (char**) &src, 10);
} else {
ret->vector = 1;
}
ret->next = primitiveDatabase[hash];
primitiveDatabase[hash] = ret;
return (Type*) ret;
}
size_t type_size(Type *t) {
if(t->type == TYPE_TYPE_PRIMITIVE) {
/* Round to nearest highest power of two. */
uint16_t w = (t->primitive.width + 7) / 8;
w--;
w |= w >> 1;
w |= w >> 2;
w |= w >> 4;
w |= w >> 8;
w++;
return w;
} else if(t->type == TYPE_TYPE_POINTER || t->type == TYPE_TYPE_FUNCTION) {
return 4;
} else if(t->type == TYPE_TYPE_ARRAY) {
return type_size(t->array.of) * t->array.length;
}
abort();
return -1;
}
int type_equal(Type *O, Type *T) {
if(O == T) return 1;
if(O->type != T->type) return 0;
if(O->type == TYPE_TYPE_PRIMITIVE) {
TypePrimitive *o = &O->primitive, *t = &T->primitive;
return o->width == t->width \
&& o->base == t->base \
&& o->isFloat == t->isFloat \
&& o->isUnsigned == t->isUnsigned \
&& o->isNative == t->isNative \
&& o->isMinimum == t->isMinimum \
&& o->vector == t->vector;
} else if(O->type == TYPE_TYPE_POINTER) {
return type_equal(O->pointer.of, T->pointer.of);
} else if(O->type == TYPE_TYPE_ARRAY) {
return type_equal(O->array.of, T->array.of) && O->array.length == T->array.length;
} else if(O->type == TYPE_TYPE_FUNCTION) {
if(!type_equal(O->function.ret, T->function.ret)) {
return 0;
}
if(O->function.argCount != T->function.argCount) {
return 0;
}
for(int i = 0; i < O->function.argCount; i++) {
if(!type_equal(O->function.args[i], T->function.args[i])) {
return 0;
}
// Don't compare argument names
}
return 1;
}
/* Consider nominal typing. */
return 0;
}
/* TODO: cache */
Type *type_pointer_wrap(Type *t) {
TypePointer *ret = malloc(sizeof(*ret));
ret->type = TYPE_TYPE_POINTER;
ret->of = t;
return (Type*) ret;
}
int type_is_number(Type *t) {
return t->type == TYPE_TYPE_POINTER || t->type == TYPE_TYPE_PRIMITIVE;
}
int type_is_castable(Type *from, Type *to) {
if(type_equal(from, to)) return 2;
if(from->type == TYPE_TYPE_POINTER && to->type == TYPE_TYPE_POINTER) {
return 2;
}
if(from->type == TYPE_TYPE_PRIMITIVE && to->type == TYPE_TYPE_PRIMITIVE) {
if(from->primitive.width > to->primitive.width) {
return 1;
} else {
return 2;
}
}
if(from->type == TYPE_TYPE_PRIMITIVE && to->type == TYPE_TYPE_POINTER) {
return 2;
}
return 0;
}