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