178 lines
3.4 KiB
C
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;
|
|
}
|