src/Types.cpp
author David Anderson <dvander@alliedmods.net>
Mon Dec 24 16:09:13 2012 -0800 (2012-12-24)
changeset 236 072f1114ea5d
parent 235 43287eef2fff
child 238 e9bec7549c28
permissions -rw-r--r--
Re-implement array assignment.
     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 Type *
    29 Type::NewVoid(Zone *zone)
    30 {
    31     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    32     if (!type)
    33         return NULL;
    34 
    35     type->kind_ = VOID;
    36     return type;
    37 }
    38 
    39 Type *
    40 Type::NewString(Zone *zone)
    41 {
    42     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    43     if (!type)
    44         return NULL;
    45 
    46     type->kind_ = STRING;
    47     return type;
    48 }
    49 
    50 Type *
    51 Type::NewUnchecked(Zone *zone)
    52 {
    53     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    54     if (!type)
    55         return NULL;
    56 
    57     type->kind_ = UNCHECKED;
    58     return type;
    59 }
    60 
    61 Type *
    62 Type::NewPrimitive(Zone *zone, PrimitiveType prim)
    63 {
    64     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    65     if (!type)
    66         return NULL;
    67 
    68     type->kind_ = PRIMITIVE;
    69     type->primitive_ = prim;
    70     return type;
    71 }
    72 
    73 ArrayType *
    74 ArrayType::New(Zone *zone, Handle<Type> contained, int elements)
    75 {
    76     if (contained->isArray() &&
    77         ArrayType::cast(contained)->levels() == MAX_ARRAY_DEPTH)
    78     {
    79         zone->reportError(Message_MaximumArrayDepth);
    80         return NULL;
    81     }
    82 
    83     Local<ArrayType> type(zone, ArrayType::cast(zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old)));
    84     if (!type)
    85         return NULL;
    86 
    87     type->kind_ = ARRAY;
    88     type->contained_ = contained;
    89     type->elements_ = elements;
    90     if (!contained->isArray())
    91         type->levels_ = 1;
    92     else
    93         type->levels_ = ArrayType::cast(contained)->levels() + 1;
    94     return type;
    95 }
    96 
    97 ArrayType *
    98 ArrayType::NewExternal(Zone *zone, Handle<Type> contained)
    99 {
   100     Local<ArrayType> type(zone, ArrayType::cast(zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old)));
   101     if (!type)
   102         return NULL;
   103 
   104     assert(contained->isPrimitive());
   105 
   106     type->kind_ = EXTERNAL_ARRAY;
   107     type->contained_ = contained;
   108     type->elements_ = DYNAMIC_ARRAY_SIZE;
   109     type->levels_ = 1;
   110     return type;
   111 }
   112 
   113 ReferenceType *
   114 ReferenceType::New(Zone *zone, Handle<Type> contained)
   115 {
   116     Local<ReferenceType> type(zone, ReferenceType::cast(zone->allocate(MapKind_ReferenceType, sizeof(ReferenceType), Heap::Tenure_Old)));
   117     if (!type)
   118         return NULL;
   119 
   120     type->kind_ = REFERENCE;
   121     type->const_ = false;
   122     type->contained_ = contained;
   123     return type;
   124 }
   125 
   126 EnumType *
   127 EnumType::New(Zone *zone, Handle<String> name)
   128 {
   129     Local<EnumType> type(zone, EnumType::cast(zone->allocate(MapKind_EnumType, sizeof(EnumType), Heap::Tenure_Old)));
   130     if (!type)
   131         return NULL;
   132 
   133     type->kind_ = ENUM;
   134     type->name_ = name;
   135     return type;
   136 }
   137 
   138 StructType *
   139 StructType::New(Zone *zone, Handle<String> name, Handle<FixedArray> fields)
   140 {
   141     Local<StructType> type(zone, StructType::cast(zone->allocate(MapKind_StructType, sizeof(StructType), Heap::Tenure_Old)));
   142     if (!type)
   143         return NULL;
   144 
   145     type->kind_ = STRUCT;
   146     type->newMap_ = NULL;
   147     type->fields_ = fields;
   148     type->name_ = name;
   149 
   150     // Fill in field offsets.
   151     StructureBufferBuilder builder;
   152     Local<Type> fieldType(zone);
   153     for (size_t i = 0; i < fields->length(); i++) {
   154         Descriptor *desc = Descriptor::cast(fields->at(i));
   155         fieldType = desc->type();
   156 
   157         unsigned offset;
   158         if (!builder.add(fieldType, &offset))
   159             return NULL;
   160         desc->setOffset(offset);
   161     }
   162 
   163     Local<StructMap> map(zone, StructMap::New(zone, builder, type));
   164     if (!map)
   165         return NULL;
   166 
   167     type->newMap_ = map;
   168 
   169     return type;
   170 }
   171 
   172 Descriptor *
   173 StructType::lookupField(Handle<String> name, unsigned *index)
   174 {
   175     for (unsigned i = 0; i < fields_->length(); i++) {
   176         Descriptor *desc = Descriptor::cast(fields_->at(i));
   177         if (desc->name() == name) {
   178             if (index)
   179                 *index = i;
   180             return desc;
   181         }
   182     }
   183 
   184     return NULL;
   185 }
   186 
   187 FunctionType *
   188 FunctionType::New(Zone *zone, Handle<String> name, TokenKind token)
   189 {
   190     Local<FunctionType> type(zone, FunctionType::cast(zone->allocate(MapKind_FunctionType, sizeof(FunctionType), Heap::Tenure_Old)));
   191     if (!type)
   192         return NULL;
   193 
   194     type->kind_ = FUNCTION;
   195     type->parameters_ = NULL;
   196     type->defaults_ = NULL;
   197     type->returnType_ = NULL;
   198     type->name_ = name;
   199     type->token_ = token;
   200     return type;
   201 }
   202 
   203 // :TODO: this leaks an interior pointer.
   204 const char *
   205 ke::GetTypeName(Type *type)
   206 {
   207     if (type->isArray())
   208         return "array";
   209     if (type->isFunction())
   210         return "function";
   211     if (type->isVoid())
   212         return "void";
   213     if (type->isEnum())
   214         return EnumType::cast(type)->name()->chars();
   215     if (type->isStruct())
   216         return StructType::cast(type)->name()->chars();
   217     if (type->isReference())
   218         type = ReferenceType::cast(type)->contained();
   219     switch (type->primitive()) {
   220       case PrimitiveType_Bool:
   221         return "bool";
   222       case PrimitiveType_Char:
   223         return "String";
   224       case PrimitiveType_Int32:
   225         return "int";
   226       case PrimitiveType_Float:
   227         return "Float";
   228       default:
   229         return "<unknown>";
   230     }
   231 }
   232