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