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