#include"types.h" #include"utils.h" #include #include #include #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; }