src/Types.cpp
author David Anderson <dvander@alliedmods.net>
Tue Dec 25 17:02:07 2012 -0800 (2012-12-25)
changeset 239 572668ef742b
parent 238 e9bec7549c28
child 240 e3c851a14f16
permissions -rw-r--r--
More const preparation: allow type casts to follow qualification.
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@238
    29
Type::init(Kind kind)
dvander@238
    30
{
dvander@238
    31
    this->kind_ = kind;
dvander@238
    32
    this->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@209
    80
ArrayType *
dvander@209
    81
ArrayType::New(Zone *zone, Handle<Type> contained, int elements)
dvander@4
    82
{
dvander@212
    83
    if (contained->isArray() &&
dvander@212
    84
        ArrayType::cast(contained)->levels() == MAX_ARRAY_DEPTH)
dvander@212
    85
    {
dvander@212
    86
        zone->reportError(Message_MaximumArrayDepth);
dvander@212
    87
        return NULL;
dvander@212
    88
    }
dvander@212
    89
dvander@239
    90
    Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
dvander@41
    91
    if (!type)
dvander@11
    92
        return NULL;
dvander@11
    93
dvander@238
    94
    type->init(ARRAY);
dvander@13
    95
    type->contained_ = contained;
dvander@13
    96
    type->elements_ = elements;
dvander@145
    97
    if (!contained->isArray())
dvander@13
    98
        type->levels_ = 1;
dvander@13
    99
    else
dvander@209
   100
        type->levels_ = ArrayType::cast(contained)->levels() + 1;
dvander@0
   101
    return type;
dvander@0
   102
}
dvander@14
   103
dvander@209
   104
ArrayType *
dvander@209
   105
ArrayType::NewExternal(Zone *zone, Handle<Type> contained)
dvander@188
   106
{
dvander@239
   107
    Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
dvander@188
   108
    if (!type)
dvander@188
   109
        return NULL;
dvander@188
   110
dvander@188
   111
    assert(contained->isPrimitive());
dvander@188
   112
dvander@238
   113
    type->init(EXTERNAL_ARRAY);
dvander@188
   114
    type->contained_ = contained;
dvander@188
   115
    type->elements_ = DYNAMIC_ARRAY_SIZE;
dvander@188
   116
    type->levels_ = 1;
dvander@188
   117
    return type;
dvander@188
   118
}
dvander@188
   119
dvander@222
   120
ReferenceType *
dvander@222
   121
ReferenceType::New(Zone *zone, Handle<Type> contained)
dvander@14
   122
{
dvander@239
   123
    Local<ReferenceType> type(zone, (ReferenceType *)zone->allocate(MapKind_ReferenceType, sizeof(ReferenceType), Heap::Tenure_Old));
dvander@41
   124
    if (!type)
dvander@14
   125
        return NULL;
dvander@14
   126
dvander@238
   127
    type->init(REFERENCE);
dvander@222
   128
    type->contained_ = contained;
dvander@14
   129
    return type;
dvander@14
   130
}
dvander@14
   131
dvander@233
   132
EnumType *
dvander@233
   133
EnumType::New(Zone *zone, Handle<String> name)
dvander@145
   134
{
dvander@239
   135
    Local<EnumType> type(zone, (EnumType *)zone->allocate(MapKind_EnumType, sizeof(EnumType), Heap::Tenure_Old));
dvander@145
   136
    if (!type)
dvander@145
   137
        return NULL;
dvander@145
   138
dvander@238
   139
    type->init(ENUM);
dvander@145
   140
    type->name_ = name;
dvander@146
   141
    return type;
dvander@146
   142
}
dvander@146
   143
dvander@195
   144
StructType *
dvander@195
   145
StructType::New(Zone *zone, Handle<String> name, Handle<FixedArray> fields)
dvander@148
   146
{
dvander@239
   147
    Local<StructType> type(zone, (StructType *)zone->allocate(MapKind_StructType, sizeof(StructType), Heap::Tenure_Old));
dvander@195
   148
    if (!type)
dvander@195
   149
        return NULL;
dvander@195
   150
dvander@238
   151
    type->init(STRUCT);
dvander@195
   152
    type->newMap_ = NULL;
dvander@195
   153
    type->fields_ = fields;
dvander@233
   154
    type->name_ = name;
dvander@195
   155
dvander@195
   156
    // Fill in field offsets.
dvander@195
   157
    StructureBufferBuilder builder;
dvander@195
   158
    Local<Type> fieldType(zone);
dvander@195
   159
    for (size_t i = 0; i < fields->length(); i++) {
dvander@195
   160
        Descriptor *desc = Descriptor::cast(fields->at(i));
dvander@195
   161
        fieldType = desc->type();
dvander@148
   162
dvander@195
   163
        unsigned offset;
dvander@195
   164
        if (!builder.add(fieldType, &offset))
dvander@195
   165
            return NULL;
dvander@195
   166
        desc->setOffset(offset);
dvander@195
   167
    }
dvander@195
   168
dvander@195
   169
    Local<StructMap> map(zone, StructMap::New(zone, builder, type));
dvander@195
   170
    if (!map)
dvander@195
   171
        return NULL;
dvander@195
   172
dvander@195
   173
    type->newMap_ = map;
dvander@195
   174
dvander@195
   175
    return type;
dvander@195
   176
}
dvander@195
   177
dvander@195
   178
Descriptor *
dvander@195
   179
StructType::lookupField(Handle<String> name, unsigned *index)
dvander@195
   180
{
dvander@148
   181
    for (unsigned i = 0; i < fields_->length(); i++) {
dvander@148
   182
        Descriptor *desc = Descriptor::cast(fields_->at(i));
dvander@148
   183
        if (desc->name() == name) {
dvander@195
   184
            if (index)
dvander@195
   185
                *index = i;
dvander@148
   186
            return desc;
dvander@148
   187
        }
dvander@148
   188
    }
dvander@148
   189
dvander@148
   190
    return NULL;
dvander@148
   191
}
dvander@148
   192
dvander@195
   193
FunctionType *
dvander@233
   194
FunctionType::New(Zone *zone, Handle<String> name, TokenKind token)
dvander@195
   195
{
dvander@239
   196
    Local<FunctionType> type(zone, (FunctionType *)zone->allocate(MapKind_FunctionType, sizeof(FunctionType), Heap::Tenure_Old));
dvander@195
   197
    if (!type)
dvander@195
   198
        return NULL;
dvander@195
   199
dvander@238
   200
    type->init(FUNCTION);
dvander@195
   201
    type->parameters_ = NULL;
dvander@195
   202
    type->defaults_ = NULL;
dvander@195
   203
    type->returnType_ = NULL;
dvander@233
   204
    type->name_ = name;
dvander@195
   205
    type->token_ = token;
dvander@195
   206
    return type;
dvander@195
   207
}
dvander@195
   208
dvander@195
   209
// :TODO: this leaks an interior pointer.
dvander@195
   210
const char *
dvander@195
   211
ke::GetTypeName(Type *type)
dvander@195
   212
{
dvander@195
   213
    if (type->isArray())
dvander@195
   214
        return "array";
dvander@195
   215
    if (type->isFunction())
dvander@195
   216
        return "function";
dvander@195
   217
    if (type->isVoid())
dvander@195
   218
        return "void";
dvander@233
   219
    if (type->isEnum())
dvander@233
   220
        return EnumType::cast(type)->name()->chars();
dvander@233
   221
    if (type->isStruct())
dvander@233
   222
        return StructType::cast(type)->name()->chars();
dvander@195
   223
    if (type->isReference())
dvander@222
   224
        type = ReferenceType::cast(type)->contained();
dvander@195
   225
    switch (type->primitive()) {
dvander@195
   226
      case PrimitiveType_Bool:
dvander@195
   227
        return "bool";
dvander@195
   228
      case PrimitiveType_Char:
dvander@195
   229
        return "String";
dvander@195
   230
      case PrimitiveType_Int32:
dvander@195
   231
        return "int";
dvander@195
   232
      case PrimitiveType_Float:
dvander@195
   233
        return "Float";
dvander@195
   234
      default:
dvander@195
   235
        return "<unknown>";
dvander@195
   236
    }
dvander@195
   237
}
dvander@195
   238