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