Initial commit
This commit is contained in:
155
src/types.c
Normal file
155
src/types.c
Normal file
@@ -0,0 +1,155 @@
|
||||
#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 = 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;
|
||||
}
|
||||
|
||||
/* 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_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;
|
||||
}
|
||||
Reference in New Issue
Block a user