src/Types.cpp
author David Anderson <dvander@alliedmods.net>
Sun Jan 06 13:52:21 2013 -0800 (2013-01-06)
changeset 256 3c184218462d
parent 241 18f3010a358c
child 258 241d082d6d89
permissions -rw-r--r--
Initial implementation of module imports.
     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 "Array.h"
    24 #include "Structures.h"
    25 #include "Heap-inl.h"
    26 
    27 using namespace ke;
    28 
    29 void
    30 Type::init(Kind kind, Type *root)
    31 {
    32     this->kind_ = kind;
    33     this->root_ = root ? root : this;
    34 }
    35 
    36 Type *
    37 Type::NewVoid(Zone *zone)
    38 {
    39     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    40     if (!type)
    41         return NULL;
    42 
    43     type->init(VOID);
    44     return type;
    45 }
    46 
    47 Type *
    48 Type::NewImportable(Zone *zone)
    49 {
    50     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    51     if (!type)
    52         return NULL;
    53 
    54     type->init(IMPORTABLE);
    55     return type;
    56 }
    57 
    58 Type *
    59 Type::NewString(Zone *zone)
    60 {
    61     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    62     if (!type)
    63         return NULL;
    64 
    65     type->init(STRING);
    66     return type;
    67 }
    68 
    69 Type *
    70 Type::NewUnchecked(Zone *zone)
    71 {
    72     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    73     if (!type)
    74         return NULL;
    75 
    76     type->init(UNCHECKED);
    77     return type;
    78 }
    79 
    80 Type *
    81 Type::NewPrimitive(Zone *zone, PrimitiveType prim)
    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(PRIMITIVE);
    88     type->primitive_ = prim;
    89     return type;
    90 }
    91 
    92 Type *
    93 Type::NewQualified(Zone *zone, TypeQualifiers qual, Handle<Type> root)
    94 {
    95     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    96     if (!type)
    97         return NULL;
    98 
    99     type->init(QUALTYPE, root);
   100     type->quals_ = qual;
   101     return type;
   102 }
   103 
   104 ArrayType *
   105 ArrayType::New(Zone *zone, Handle<Type> contained, int elements)
   106 {
   107     if (contained->isArray() &&
   108         ArrayType::cast(contained)->levels() == MAX_ARRAY_DEPTH)
   109     {
   110         zone->reportError(Message_MaximumArrayDepth);
   111         return NULL;
   112     }
   113 
   114     Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
   115     if (!type)
   116         return NULL;
   117 
   118     type->init(ARRAY);
   119     type->contained_ = contained;
   120     type->elements_ = elements;
   121     if (!contained->isArray())
   122         type->levels_ = 1;
   123     else
   124         type->levels_ = ArrayType::cast(contained)->levels() + 1;
   125 
   126     type->newMap_ = ArrayMap::New(zone, type);
   127     if (!type->newMap_)
   128         return NULL;
   129 
   130     return type;
   131 }
   132 
   133 ArrayType *
   134 ArrayType::NewExternal(Zone *zone, Handle<Type> contained)
   135 {
   136     Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
   137     if (!type)
   138         return NULL;
   139 
   140     assert(contained->isPrimitive());
   141 
   142     type->init(EXTERNAL_ARRAY);
   143     type->contained_ = contained;
   144     type->elements_ = DYNAMIC_ARRAY_SIZE;
   145     type->levels_ = 1;
   146     return type;
   147 }
   148 
   149 ReferenceType *
   150 ReferenceType::New(Zone *zone, Handle<Type> contained)
   151 {
   152     Local<ReferenceType> type(zone, (ReferenceType *)zone->allocate(MapKind_ReferenceType, sizeof(ReferenceType), Heap::Tenure_Old));
   153     if (!type)
   154         return NULL;
   155 
   156     type->init(REFERENCE);
   157     type->contained_ = contained;
   158     return type;
   159 }
   160 
   161 EnumType *
   162 EnumType::New(Zone *zone, Handle<String> name)
   163 {
   164     Local<EnumType> type(zone, (EnumType *)zone->allocate(MapKind_EnumType, sizeof(EnumType), Heap::Tenure_Old));
   165     if (!type)
   166         return NULL;
   167 
   168     type->init(ENUM);
   169     type->name_ = name;
   170     return type;
   171 }
   172 
   173 StructType *
   174 StructType::New(Zone *zone, Handle<String> name, Handle<FixedArray> fields)
   175 {
   176     Local<StructType> type(zone, (StructType *)zone->allocate(MapKind_StructType, sizeof(StructType), Heap::Tenure_Old));
   177     if (!type)
   178         return NULL;
   179 
   180     type->init(STRUCT);
   181     type->newMap_ = NULL;
   182     type->fields_ = fields;
   183     type->name_ = name;
   184 
   185     // Fill in field offsets.
   186     StructureBufferBuilder builder;
   187     Local<Type> fieldType(zone);
   188     for (size_t i = 0; i < fields->length(); i++) {
   189         Descriptor *desc = Descriptor::cast(fields->at(i));
   190         fieldType = desc->type();
   191 
   192         unsigned offset;
   193         if (!builder.add(fieldType, &offset))
   194             return NULL;
   195         desc->setOffset(offset);
   196     }
   197 
   198     Local<StructMap> map(zone, StructMap::New(zone, builder, type));
   199     if (!map)
   200         return NULL;
   201 
   202     type->newMap_ = map;
   203 
   204     return type;
   205 }
   206 
   207 Descriptor *
   208 StructType::lookupField(Handle<String> name, unsigned *index)
   209 {
   210     for (unsigned i = 0; i < fields_->length(); i++) {
   211         Descriptor *desc = Descriptor::cast(fields_->at(i));
   212         if (desc->name() == name) {
   213             if (index)
   214                 *index = i;
   215             return desc;
   216         }
   217     }
   218 
   219     return NULL;
   220 }
   221 
   222 FunctionType *
   223 FunctionType::New(Zone *zone, Handle<String> name, TokenKind token)
   224 {
   225     Local<FunctionType> type(zone, (FunctionType *)zone->allocate(MapKind_FunctionType, sizeof(FunctionType), Heap::Tenure_Old));
   226     if (!type)
   227         return NULL;
   228 
   229     type->init(FUNCTION);
   230     type->parameters_ = NULL;
   231     type->defaults_ = NULL;
   232     type->returnType_ = NULL;
   233     type->name_ = name;
   234     type->token_ = token;
   235     return type;
   236 }
   237 
   238 static size_t
   239 FormatVA(char *buffer, size_t maxlen, const char *text, va_list ap)
   240 {
   241     size_t len = vsnprintf(buffer, maxlen, text, ap);
   242     if (len >= maxlen) {
   243         buffer[maxlen - 1] = '\0';
   244         return maxlen - 1;
   245     }
   246     return len;
   247 }
   248 
   249 static size_t
   250 Format(char *buffer, size_t maxlen, const char *text, ...)
   251 {
   252     va_list ap;
   253     va_start(ap, text);
   254     size_t len = FormatVA(buffer, maxlen, text, ap);
   255     va_end(ap);
   256     return len;
   257 }
   258 
   259 static size_t
   260 FormatTypeName(Type *type, char *buffer, size_t maxlen)
   261 {
   262     if (type->isArray()) {
   263         ArrayType *atype = ArrayType::cast(type);
   264         Type *innermost = atype->innermost();
   265 
   266         size_t len = FormatTypeName(innermost, buffer, maxlen);
   267         for (;;) {
   268             if (atype->isFixedLength())
   269                 len += Format(buffer + len, maxlen - len, "[%d]", atype->fixedLength());
   270             else
   271                 len += Format(buffer + len, maxlen - len, "[]");
   272             if (!atype->contained()->isArray())
   273                 break;
   274             atype = ArrayType::cast(atype->contained());
   275         }
   276         return len;
   277     }
   278     if (type->hasTypeQualifiers()) {
   279         size_t len = 0;
   280         if (type->quals() & TypeQual_Const)
   281             len += Format(buffer, maxlen, "const ");
   282         return len + FormatTypeName(type->unqualified(), buffer + len, maxlen - len);
   283     }
   284     if (type->isFunction())
   285         return Format(buffer, maxlen, "function");
   286     if (type->isVoid())
   287         return Format(buffer, maxlen, "void");
   288     if (type->isUnchecked())
   289         return Format(buffer, maxlen, "unchecked");
   290     if (type->isImportable())
   291         return Format(buffer, maxlen, "import");
   292     if (type->isEnum())
   293         return Format(buffer, maxlen, "%s", EnumType::cast(type)->name()->chars());
   294     if (type->isStruct())
   295         return Format(buffer, maxlen, "%s", StructType::cast(type)->name()->chars());
   296     if (type->isReference()) {
   297         ReferenceType *ref = ReferenceType::cast(type);
   298         size_t len = Format(buffer, maxlen, "&");
   299         return len + FormatTypeName(ref->contained(), buffer + len, maxlen - len);
   300     }
   301     switch (type->primitive()) {
   302       case PrimitiveType_Bool:
   303         return Format(buffer, maxlen, "bool");
   304       case PrimitiveType_Char:
   305         return Format(buffer, maxlen, "char");
   306       case PrimitiveType_Int32:
   307         return Format(buffer, maxlen, "int");
   308       case PrimitiveType_Float:
   309         return Format(buffer, maxlen, "float");
   310       default:
   311         return Format(buffer, maxlen, "<UNKNOWN>");
   312     }
   313 }
   314 
   315 const char *
   316 ke::GetTypeName(Type *type, char *buffer, size_t maxlen)
   317 {
   318     FormatTypeName(type, buffer, maxlen);
   319     return buffer;
   320 }