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.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of SourcePawn.
     6  *
     7  * SourcePawn is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * SourcePawn. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #include <string.h>
    20 #include "Types.h"
    21 #include "Zone.h"
    22 #include "Strings.h"
    23 #include "Structures.h"
    24 #include "Heap-inl.h"
    25 
    26 using namespace ke;
    27 
    28 void
    29 Type::init(Kind kind)
    30 {
    31     this->kind_ = kind;
    32     this->root_ = this;
    33 }
    34 
    35 Type *
    36 Type::NewVoid(Zone *zone)
    37 {
    38     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    39     if (!type)
    40         return NULL;
    41 
    42     type->init(VOID);
    43     return type;
    44 }
    45 
    46 Type *
    47 Type::NewString(Zone *zone)
    48 {
    49     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    50     if (!type)
    51         return NULL;
    52 
    53     type->init(STRING);
    54     return type;
    55 }
    56 
    57 Type *
    58 Type::NewUnchecked(Zone *zone)
    59 {
    60     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    61     if (!type)
    62         return NULL;
    63 
    64     type->init(UNCHECKED);
    65     return type;
    66 }
    67 
    68 Type *
    69 Type::NewPrimitive(Zone *zone, PrimitiveType prim)
    70 {
    71     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    72     if (!type)
    73         return NULL;
    74 
    75     type->init(PRIMITIVE);
    76     type->primitive_ = prim;
    77     return type;
    78 }
    79 
    80 ArrayType *
    81 ArrayType::New(Zone *zone, Handle<Type> contained, int elements)
    82 {
    83     if (contained->isArray() &&
    84         ArrayType::cast(contained)->levels() == MAX_ARRAY_DEPTH)
    85     {
    86         zone->reportError(Message_MaximumArrayDepth);
    87         return NULL;
    88     }
    89 
    90     Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
    91     if (!type)
    92         return NULL;
    93 
    94     type->init(ARRAY);
    95     type->contained_ = contained;
    96     type->elements_ = elements;
    97     if (!contained->isArray())
    98         type->levels_ = 1;
    99     else
   100         type->levels_ = ArrayType::cast(contained)->levels() + 1;
   101     return type;
   102 }
   103 
   104 ArrayType *
   105 ArrayType::NewExternal(Zone *zone, Handle<Type> contained)
   106 {
   107     Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
   108     if (!type)
   109         return NULL;
   110 
   111     assert(contained->isPrimitive());
   112 
   113     type->init(EXTERNAL_ARRAY);
   114     type->contained_ = contained;
   115     type->elements_ = DYNAMIC_ARRAY_SIZE;
   116     type->levels_ = 1;
   117     return type;
   118 }
   119 
   120 ReferenceType *
   121 ReferenceType::New(Zone *zone, Handle<Type> contained)
   122 {
   123     Local<ReferenceType> type(zone, (ReferenceType *)zone->allocate(MapKind_ReferenceType, sizeof(ReferenceType), Heap::Tenure_Old));
   124     if (!type)
   125         return NULL;
   126 
   127     type->init(REFERENCE);
   128     type->contained_ = contained;
   129     return type;
   130 }
   131 
   132 EnumType *
   133 EnumType::New(Zone *zone, Handle<String> name)
   134 {
   135     Local<EnumType> type(zone, (EnumType *)zone->allocate(MapKind_EnumType, sizeof(EnumType), Heap::Tenure_Old));
   136     if (!type)
   137         return NULL;
   138 
   139     type->init(ENUM);
   140     type->name_ = name;
   141     return type;
   142 }
   143 
   144 StructType *
   145 StructType::New(Zone *zone, Handle<String> name, Handle<FixedArray> fields)
   146 {
   147     Local<StructType> type(zone, (StructType *)zone->allocate(MapKind_StructType, sizeof(StructType), Heap::Tenure_Old));
   148     if (!type)
   149         return NULL;
   150 
   151     type->init(STRUCT);
   152     type->newMap_ = NULL;
   153     type->fields_ = fields;
   154     type->name_ = name;
   155 
   156     // Fill in field offsets.
   157     StructureBufferBuilder builder;
   158     Local<Type> fieldType(zone);
   159     for (size_t i = 0; i < fields->length(); i++) {
   160         Descriptor *desc = Descriptor::cast(fields->at(i));
   161         fieldType = desc->type();
   162 
   163         unsigned offset;
   164         if (!builder.add(fieldType, &offset))
   165             return NULL;
   166         desc->setOffset(offset);
   167     }
   168 
   169     Local<StructMap> map(zone, StructMap::New(zone, builder, type));
   170     if (!map)
   171         return NULL;
   172 
   173     type->newMap_ = map;
   174 
   175     return type;
   176 }
   177 
   178 Descriptor *
   179 StructType::lookupField(Handle<String> name, unsigned *index)
   180 {
   181     for (unsigned i = 0; i < fields_->length(); i++) {
   182         Descriptor *desc = Descriptor::cast(fields_->at(i));
   183         if (desc->name() == name) {
   184             if (index)
   185                 *index = i;
   186             return desc;
   187         }
   188     }
   189 
   190     return NULL;
   191 }
   192 
   193 FunctionType *
   194 FunctionType::New(Zone *zone, Handle<String> name, TokenKind token)
   195 {
   196     Local<FunctionType> type(zone, (FunctionType *)zone->allocate(MapKind_FunctionType, sizeof(FunctionType), Heap::Tenure_Old));
   197     if (!type)
   198         return NULL;
   199 
   200     type->init(FUNCTION);
   201     type->parameters_ = NULL;
   202     type->defaults_ = NULL;
   203     type->returnType_ = NULL;
   204     type->name_ = name;
   205     type->token_ = token;
   206     return type;
   207 }
   208 
   209 // :TODO: this leaks an interior pointer.
   210 const char *
   211 ke::GetTypeName(Type *type)
   212 {
   213     if (type->isArray())
   214         return "array";
   215     if (type->isFunction())
   216         return "function";
   217     if (type->isVoid())
   218         return "void";
   219     if (type->isEnum())
   220         return EnumType::cast(type)->name()->chars();
   221     if (type->isStruct())
   222         return StructType::cast(type)->name()->chars();
   223     if (type->isReference())
   224         type = ReferenceType::cast(type)->contained();
   225     switch (type->primitive()) {
   226       case PrimitiveType_Bool:
   227         return "bool";
   228       case PrimitiveType_Char:
   229         return "String";
   230       case PrimitiveType_Int32:
   231         return "int";
   232       case PrimitiveType_Float:
   233         return "Float";
   234       default:
   235         return "<unknown>";
   236     }
   237 }
   238