src/Types.cpp
author Michael Busby <prodigysim@gmail.com>
Mon Jun 10 01:50:18 2013 +0100 (2013-06-10)
changeset 264 70b8f318c379
parent 263 ba85a47ee414
permissions -rw-r--r--
Parse assignment RTL instead of LTR, fixes multiple assignment (bug 5420).
     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::NewType(Zone *zone)
    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(TYPE);
    88     return type;
    89 }
    90 
    91 Type *
    92 Type::NewPrimitive(Zone *zone, PrimitiveType prim)
    93 {
    94     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    95     if (!type)
    96         return NULL;
    97 
    98     type->init(PRIMITIVE);
    99     type->primitive_ = prim;
   100     return type;
   101 }
   102 
   103 Type *
   104 Type::NewQualified(Zone *zone, TypeQualifiers qual, Handle<Type> root)
   105 {
   106     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   107     if (!type)
   108         return NULL;
   109 
   110     type->init(QUALTYPE, root);
   111     type->quals_ = qual;
   112     return type;
   113 }
   114 
   115 ArrayType *
   116 ArrayType::New(Zone *zone, Handle<Type> contained, int elements)
   117 {
   118     if (contained->isArray() &&
   119         ArrayType::cast(contained)->levels() == MAX_ARRAY_DEPTH)
   120     {
   121         zone->reportError(Message_MaximumArrayDepth);
   122         return NULL;
   123     }
   124 
   125     Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
   126     if (!type)
   127         return NULL;
   128 
   129     type->init(ARRAY);
   130     type->contained_ = contained;
   131     type->elements_ = elements;
   132     if (!contained->isArray())
   133         type->levels_ = 1;
   134     else
   135         type->levels_ = ArrayType::cast(contained)->levels() + 1;
   136 
   137     type->newMap_ = ArrayMap::New(zone, type);
   138     if (!type->newMap_)
   139         return NULL;
   140 
   141     return type;
   142 }
   143 
   144 ArrayType *
   145 ArrayType::NewExternal(Zone *zone, Handle<Type> contained)
   146 {
   147     Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
   148     if (!type)
   149         return NULL;
   150 
   151     assert(contained->isPrimitive());
   152 
   153     type->init(EXTERNAL_ARRAY);
   154     type->contained_ = contained;
   155     type->elements_ = DYNAMIC_ARRAY_SIZE;
   156     type->levels_ = 1;
   157     return type;
   158 }
   159 
   160 ReferenceType *
   161 ReferenceType::New(Zone *zone, Handle<Type> contained)
   162 {
   163     Local<ReferenceType> type(zone, (ReferenceType *)zone->allocate(MapKind_ReferenceType, sizeof(ReferenceType), Heap::Tenure_Old));
   164     if (!type)
   165         return NULL;
   166 
   167     type->init(REFERENCE);
   168     type->contained_ = contained;
   169     return type;
   170 }
   171 
   172 EnumType *
   173 EnumType::New(Zone *zone, Handle<String> name)
   174 {
   175     Local<EnumType> type(zone, (EnumType *)zone->allocate(MapKind_EnumType, sizeof(EnumType), Heap::Tenure_Old));
   176     if (!type)
   177         return NULL;
   178 
   179     type->init(ENUM);
   180     type->name_ = name;
   181     type->fields_ = NULL;
   182     return type;
   183 }
   184 
   185 StructType *
   186 StructType::New(Zone *zone, Handle<String> name, Handle<FixedArray> fields)
   187 {
   188     Local<StructType> type(zone, (StructType *)zone->allocate(MapKind_StructType, sizeof(StructType), Heap::Tenure_Old));
   189     if (!type)
   190         return NULL;
   191 
   192     type->init(STRUCT);
   193     type->newMap_ = NULL;
   194     type->fields_ = fields;
   195     type->name_ = name;
   196 
   197     // Fill in field offsets.
   198     StructureBufferBuilder builder;
   199     Local<Type> fieldType(zone);
   200     for (size_t i = 0; i < fields->length(); i++) {
   201         Descriptor *desc = Descriptor::cast(fields->at(i));
   202         fieldType = desc->type();
   203 
   204         unsigned offset;
   205         if (!builder.add(fieldType, &offset))
   206             return NULL;
   207         desc->setOffset(offset);
   208     }
   209 
   210     Local<StructMap> map(zone, StructMap::New(zone, builder, type));
   211     if (!map)
   212         return NULL;
   213 
   214     type->newMap_ = map;
   215 
   216     return type;
   217 }
   218 
   219 Descriptor *
   220 StructType::lookupField(String *name, unsigned *index)
   221 {
   222     // :TODO: assert no GC
   223     for (unsigned i = 0; i < fields_->length(); i++) {
   224         Descriptor *desc = Descriptor::cast(fields_->at(i));
   225         if (desc->name() == name) {
   226             if (index)
   227                 *index = i;
   228             return desc;
   229         }
   230     }
   231 
   232     return NULL;
   233 }
   234 
   235 FunctionType *
   236 FunctionType::New(Zone *zone, Handle<String> name, TokenKind token)
   237 {
   238     Local<FunctionType> type(zone, (FunctionType *)zone->allocate(MapKind_FunctionType, sizeof(FunctionType), Heap::Tenure_Old));
   239     if (!type)
   240         return NULL;
   241 
   242     type->init(FUNCTION);
   243     type->parameters_ = NULL;
   244     type->defaults_ = NULL;
   245     type->returnType_ = NULL;
   246     type->name_ = name;
   247     type->token_ = token;
   248     return type;
   249 }
   250 
   251 static size_t
   252 FormatVA(char *buffer, size_t maxlen, const char *text, va_list ap)
   253 {
   254     size_t len = vsnprintf(buffer, maxlen, text, ap);
   255     if (len >= maxlen) {
   256         buffer[maxlen - 1] = '\0';
   257         return maxlen - 1;
   258     }
   259     return len;
   260 }
   261 
   262 static size_t
   263 Format(char *buffer, size_t maxlen, const char *text, ...)
   264 {
   265     va_list ap;
   266     va_start(ap, text);
   267     size_t len = FormatVA(buffer, maxlen, text, ap);
   268     va_end(ap);
   269     return len;
   270 }
   271 
   272 static size_t
   273 FormatTypeName(Type *type, char *buffer, size_t maxlen)
   274 {
   275     if (type->isArray()) {
   276         ArrayType *atype = ArrayType::cast(type);
   277         Type *innermost = atype->innermost();
   278 
   279         size_t len = FormatTypeName(innermost, buffer, maxlen);
   280         for (;;) {
   281             if (atype->isFixedLength())
   282                 len += Format(buffer + len, maxlen - len, "[%d]", atype->fixedLength());
   283             else
   284                 len += Format(buffer + len, maxlen - len, "[]");
   285             if (!atype->contained()->isArray())
   286                 break;
   287             atype = ArrayType::cast(atype->contained());
   288         }
   289         return len;
   290     }
   291     if (type->hasTypeQualifiers()) {
   292         size_t len = 0;
   293         if (type->quals() & TypeQual_Const)
   294             len += Format(buffer, maxlen, "const ");
   295         return len + FormatTypeName(type->unqualified(), buffer + len, maxlen - len);
   296     }
   297     if (type->isFunction())
   298         return Format(buffer, maxlen, "function");
   299     if (type->isVoid())
   300         return Format(buffer, maxlen, "void");
   301     if (type->isUnchecked())
   302         return Format(buffer, maxlen, "unchecked");
   303     if (type->isImportable())
   304         return Format(buffer, maxlen, "import");
   305     if (type->isEnum())
   306         return Format(buffer, maxlen, "%s", EnumType::cast(type)->name()->chars());
   307     if (type->isStruct())
   308         return Format(buffer, maxlen, "%s", StructType::cast(type)->name()->chars());
   309     if (type->isReference()) {
   310         ReferenceType *ref = ReferenceType::cast(type);
   311         size_t len = Format(buffer, maxlen, "&");
   312         return len + FormatTypeName(ref->contained(), buffer + len, maxlen - len);
   313     }
   314     switch (type->primitive()) {
   315       case PrimitiveType_Bool:
   316         return Format(buffer, maxlen, "bool");
   317       case PrimitiveType_Char:
   318         return Format(buffer, maxlen, "char");
   319       case PrimitiveType_Int32:
   320         return Format(buffer, maxlen, "int");
   321       case PrimitiveType_Float:
   322         return Format(buffer, maxlen, "float");
   323       default:
   324         return Format(buffer, maxlen, "<UNKNOWN>");
   325     }
   326 }
   327 
   328 const char *
   329 ke::GetTypeName(Type *type, char *buffer, size_t maxlen)
   330 {
   331     FormatTypeName(type, buffer, maxlen);
   332     return buffer;
   333 }