src/Types.cpp
author David Anderson <dvander@alliedmods.net>
Tue Jan 01 15:34:07 2013 -0800 (2013-01-01)
changeset 251 ca99a81745fe
parent 241 18f3010a358c
child 256 3c184218462d
permissions -rw-r--r--
Refactor compilation process around the new concept of packages.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of SourcePawn.
     6  *
     7  * SourcePawn is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * SourcePawn. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #include <string.h>
    20 #include "Types.h"
    21 #include "Zone.h"
    22 #include "Strings.h"
    23 #include "Structures.h"
    24 #include "Heap-inl.h"
    25 
    26 using namespace ke;
    27 
    28 void
    29 Type::init(Kind kind, Type *root)
    30 {
    31     this->kind_ = kind;
    32     this->root_ = root ? root : this;
    33 }
    34 
    35 Type *
    36 Type::NewVoid(Zone *zone)
    37 {
    38     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    39     if (!type)
    40         return NULL;
    41 
    42     type->init(VOID);
    43     return type;
    44 }
    45 
    46 Type *
    47 Type::NewString(Zone *zone)
    48 {
    49     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    50     if (!type)
    51         return NULL;
    52 
    53     type->init(STRING);
    54     return type;
    55 }
    56 
    57 Type *
    58 Type::NewUnchecked(Zone *zone)
    59 {
    60     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    61     if (!type)
    62         return NULL;
    63 
    64     type->init(UNCHECKED);
    65     return type;
    66 }
    67 
    68 Type *
    69 Type::NewPrimitive(Zone *zone, PrimitiveType prim)
    70 {
    71     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    72     if (!type)
    73         return NULL;
    74 
    75     type->init(PRIMITIVE);
    76     type->primitive_ = prim;
    77     return type;
    78 }
    79 
    80 Type *
    81 Type::NewQualified(Zone *zone, TypeQualifiers qual, Handle<Type> root)
    82 {
    83     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    84     if (!type)
    85         return NULL;
    86 
    87     type->init(QUALTYPE, root);
    88     type->quals_ = qual;
    89     return type;
    90 }
    91 
    92 ArrayType *
    93 ArrayType::New(Zone *zone, Handle<Type> contained, int elements)
    94 {
    95     if (contained->isArray() &&
    96         ArrayType::cast(contained)->levels() == MAX_ARRAY_DEPTH)
    97     {
    98         zone->reportError(Message_MaximumArrayDepth);
    99         return NULL;
   100     }
   101 
   102     Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
   103     if (!type)
   104         return NULL;
   105 
   106     type->init(ARRAY);
   107     type->contained_ = contained;
   108     type->elements_ = elements;
   109     if (!contained->isArray())
   110         type->levels_ = 1;
   111     else
   112         type->levels_ = ArrayType::cast(contained)->levels() + 1;
   113     return type;
   114 }
   115 
   116 ArrayType *
   117 ArrayType::NewExternal(Zone *zone, Handle<Type> contained)
   118 {
   119     Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
   120     if (!type)
   121         return NULL;
   122 
   123     assert(contained->isPrimitive());
   124 
   125     type->init(EXTERNAL_ARRAY);
   126     type->contained_ = contained;
   127     type->elements_ = DYNAMIC_ARRAY_SIZE;
   128     type->levels_ = 1;
   129     return type;
   130 }
   131 
   132 ReferenceType *
   133 ReferenceType::New(Zone *zone, Handle<Type> contained)
   134 {
   135     Local<ReferenceType> type(zone, (ReferenceType *)zone->allocate(MapKind_ReferenceType, sizeof(ReferenceType), Heap::Tenure_Old));
   136     if (!type)
   137         return NULL;
   138 
   139     type->init(REFERENCE);
   140     type->contained_ = contained;
   141     return type;
   142 }
   143 
   144 EnumType *
   145 EnumType::New(Zone *zone, Handle<String> name)
   146 {
   147     Local<EnumType> type(zone, (EnumType *)zone->allocate(MapKind_EnumType, sizeof(EnumType), Heap::Tenure_Old));
   148     if (!type)
   149         return NULL;
   150 
   151     type->init(ENUM);
   152     type->name_ = name;
   153     return type;
   154 }
   155 
   156 StructType *
   157 StructType::New(Zone *zone, Handle<String> name, Handle<FixedArray> fields)
   158 {
   159     Local<StructType> type(zone, (StructType *)zone->allocate(MapKind_StructType, sizeof(StructType), Heap::Tenure_Old));
   160     if (!type)
   161         return NULL;
   162 
   163     type->init(STRUCT);
   164     type->newMap_ = NULL;
   165     type->fields_ = fields;
   166     type->name_ = name;
   167 
   168     // Fill in field offsets.
   169     StructureBufferBuilder builder;
   170     Local<Type> fieldType(zone);
   171     for (size_t i = 0; i < fields->length(); i++) {
   172         Descriptor *desc = Descriptor::cast(fields->at(i));
   173         fieldType = desc->type();
   174 
   175         unsigned offset;
   176         if (!builder.add(fieldType, &offset))
   177             return NULL;
   178         desc->setOffset(offset);
   179     }
   180 
   181     Local<StructMap> map(zone, StructMap::New(zone, builder, type));
   182     if (!map)
   183         return NULL;
   184 
   185     type->newMap_ = map;
   186 
   187     return type;
   188 }
   189 
   190 Descriptor *
   191 StructType::lookupField(Handle<String> name, unsigned *index)
   192 {
   193     for (unsigned i = 0; i < fields_->length(); i++) {
   194         Descriptor *desc = Descriptor::cast(fields_->at(i));
   195         if (desc->name() == name) {
   196             if (index)
   197                 *index = i;
   198             return desc;
   199         }
   200     }
   201 
   202     return NULL;
   203 }
   204 
   205 FunctionType *
   206 FunctionType::New(Zone *zone, Handle<String> name, TokenKind token)
   207 {
   208     Local<FunctionType> type(zone, (FunctionType *)zone->allocate(MapKind_FunctionType, sizeof(FunctionType), Heap::Tenure_Old));
   209     if (!type)
   210         return NULL;
   211 
   212     type->init(FUNCTION);
   213     type->parameters_ = NULL;
   214     type->defaults_ = NULL;
   215     type->returnType_ = NULL;
   216     type->name_ = name;
   217     type->token_ = token;
   218     return type;
   219 }
   220 
   221 static size_t
   222 FormatVA(char *buffer, size_t maxlen, const char *text, va_list ap)
   223 {
   224     size_t len = vsnprintf(buffer, maxlen, text, ap);
   225     if (len >= maxlen) {
   226         buffer[maxlen - 1] = '\0';
   227         return maxlen - 1;
   228     }
   229     return len;
   230 }
   231 
   232 static size_t
   233 Format(char *buffer, size_t maxlen, const char *text, ...)
   234 {
   235     va_list ap;
   236     va_start(ap, text);
   237     size_t len = FormatVA(buffer, maxlen, text, ap);
   238     va_end(ap);
   239     return len;
   240 }
   241 
   242 static size_t
   243 FormatTypeName(Type *type, char *buffer, size_t maxlen)
   244 {
   245     if (type->isArray()) {
   246         ArrayType *atype = ArrayType::cast(type);
   247         Type *innermost = atype->innermost();
   248 
   249         size_t len = FormatTypeName(innermost, buffer, maxlen);
   250         for (;;) {
   251             if (atype->isFixedLength())
   252                 len += Format(buffer + len, maxlen - len, "[%d]", atype->fixedLength());
   253             else
   254                 len += Format(buffer + len, maxlen - len, "[]");
   255             if (!atype->contained()->isArray())
   256                 break;
   257             atype = ArrayType::cast(atype->contained());
   258         }
   259         return len;
   260     }
   261     if (type->hasTypeQualifiers()) {
   262         size_t len = 0;
   263         if (type->quals() & TypeQual_Const)
   264             len += Format(buffer, maxlen, "const ");
   265         return len + FormatTypeName(type->unqualified(), buffer + len, maxlen - len);
   266     }
   267     if (type->isFunction())
   268         return Format(buffer, maxlen, "function");
   269     if (type->isVoid())
   270         return Format(buffer, maxlen, "void");
   271     if (type->isUnchecked())
   272         return Format(buffer, maxlen, "unchecked");
   273     if (type->isEnum())
   274         return Format(buffer, maxlen, "%s", EnumType::cast(type)->name()->chars());
   275     if (type->isStruct())
   276         return Format(buffer, maxlen, "%s", StructType::cast(type)->name()->chars());
   277     if (type->isReference()) {
   278         ReferenceType *ref = ReferenceType::cast(type);
   279         size_t len = Format(buffer, maxlen, "&");
   280         return len + FormatTypeName(ref->contained(), buffer + len, maxlen - len);
   281     }
   282     switch (type->primitive()) {
   283       case PrimitiveType_Bool:
   284         return Format(buffer, maxlen, "bool");
   285       case PrimitiveType_Char:
   286         return Format(buffer, maxlen, "char");
   287       case PrimitiveType_Int32:
   288         return Format(buffer, maxlen, "int");
   289       case PrimitiveType_Float:
   290         return Format(buffer, maxlen, "float");
   291       default:
   292         return Format(buffer, maxlen, "<UNKNOWN>");
   293     }
   294 }
   295 
   296 const char *
   297 ke::GetTypeName(Type *type, char *buffer, size_t maxlen)
   298 {
   299     FormatTypeName(type, buffer, maxlen);
   300     return buffer;
   301 }