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