src/Types.cpp
author David Anderson <dvander@alliedmods.net>
Sun Sep 16 21:34:10 2012 -0700 (2012-09-16)
changeset 188 bab29bcec7fe
parent 186 03a663e96860
child 195 c1ba166f3fc4
permissions -rw-r--r--
Restructure Array so the elements vector can be replaced.
     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     type->contained_ = NULL;
    37     type->returnType_ = NULL;
    38     type->parameters_ = NULL;
    39     type->defaults_ = NULL;
    40     type->fields_ = NULL;
    41     type->newMap_ = NULL;
    42     return type;
    43 }
    44 
    45 Type *
    46 Type::NewUnchecked(Zone *zone)
    47 {
    48     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    49     if (!type)
    50         return NULL;
    51 
    52     type->kind_ = UNCHECKED;
    53     type->contained_ = NULL;
    54     type->returnType_ = NULL;
    55     type->parameters_ = NULL;
    56     type->defaults_ = NULL;
    57     type->fields_ = NULL;
    58     type->newMap_ = NULL;
    59     return type;
    60 }
    61 
    62 Type *
    63 Type::NewPrimitive(Zone *zone, PrimitiveType prim)
    64 {
    65     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    66     if (!type)
    67         return NULL;
    68 
    69     type->kind_ = PRIMITIVE;
    70     type->name_ = NULL;
    71     type->contained_ = NULL;
    72     type->returnType_ = NULL;
    73     type->parameters_ = NULL;
    74     type->defaults_ = NULL;
    75     type->fields_ = NULL;
    76     type->newMap_ = NULL;
    77     type->newMap_ = NULL;
    78     type->primitive_ = prim;
    79     return type;
    80 }
    81 
    82 Type *
    83 Type::NewArray(Zone *zone, Handle<Type> contained, int elements, bool isConst)
    84 {
    85     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    86     if (!type)
    87         return NULL;
    88 
    89     type->kind_ = ARRAY;
    90     type->name_ = NULL;
    91     type->contained_ = contained;
    92     type->returnType_ = NULL;
    93     type->parameters_ = NULL;
    94     type->defaults_ = NULL;
    95     type->fields_ = NULL;
    96     type->newMap_ = NULL;
    97     type->elements_ = elements;
    98     if (!contained->isArray())
    99         type->levels_ = 1;
   100     else
   101         type->levels_ = contained->levels() + 1;
   102     type->const_ = isConst;
   103     return type;
   104 }
   105 
   106 Type *
   107 Type::NewExternalArray(Zone *zone, Handle<Type> contained)
   108 {
   109     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   110     if (!type)
   111         return NULL;
   112 
   113     assert(contained->isPrimitive());
   114 
   115     type->kind_ = EXTERNAL_ARRAY;
   116     type->name_ = NULL;
   117     type->contained_ = contained;
   118     type->returnType_ = NULL;
   119     type->parameters_ = NULL;
   120     type->defaults_ = NULL;
   121     type->fields_ = NULL;
   122     type->newMap_ = NULL;
   123     type->elements_ = DYNAMIC_ARRAY_SIZE;
   124     type->levels_ = 1;
   125     type->const_ = false;
   126     return type;
   127 }
   128 
   129 Type *
   130 Type::NewReference(Zone *zone, Handle<Type> contained, bool isConst)
   131 {
   132     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   133     if (!type)
   134         return NULL;
   135 
   136     type->kind_ = REFERENCE;
   137     type->name_ = NULL;
   138     type->contained_ = contained;
   139     type->returnType_ = NULL;
   140     type->parameters_ = NULL;
   141     type->defaults_ = NULL;
   142     type->fields_ = NULL;
   143     type->newMap_ = NULL;
   144     type->const_ = isConst;
   145     return type;
   146 }
   147 
   148 Type *
   149 Type::NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters,
   150                   Handle<FixedArray> defaults)
   151 {
   152     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   153     if (!type)
   154         return NULL;
   155 
   156     type->kind_ = FUNCTION;
   157     type->name_ = NULL;
   158     type->contained_ = NULL;
   159     type->fields_ = NULL;
   160     type->newMap_ = NULL;
   161     type->returnType_ = returnType;
   162     type->parameters_ = parameters;
   163     type->defaults_ = defaults;
   164     return type;
   165 }
   166 
   167 Type *
   168 Type::NewEnum(Zone *zone, Handle<String> name)
   169 {
   170     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   171     if (!type)
   172         return NULL;
   173 
   174     type->kind_ = ENUM;
   175     type->name_ = name;
   176     type->contained_ = NULL;
   177     type->returnType_ = NULL;
   178     type->parameters_ = NULL;
   179     type->defaults_ = NULL;
   180     type->fields_ = NULL;
   181     type->newMap_ = NULL;
   182     return type;
   183 }
   184 
   185 Type *
   186 Type::NewStruct(Zone *zone, Handle<String> name, Handle<FixedArray> fields, Handle<Map> newMap)
   187 {
   188     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   189     if (!type)
   190         return NULL;
   191 
   192     type->kind_ = STRUCT;
   193     type->name_ = name;
   194     type->contained_ = NULL;
   195     type->returnType_ = NULL;
   196     type->parameters_ = NULL;
   197     type->defaults_ = NULL;
   198     type->newMap_ = newMap;
   199     type->fields_ = fields;
   200     return type;
   201 }
   202 
   203 Type *
   204 Type::NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters,
   205                 Handle<FixedArray> defaults, bool variadic)
   206 {
   207     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   208     if (!type)
   209         return NULL;
   210 
   211     type->kind_ = NATIVE;
   212     type->name_ = NULL;
   213     type->contained_ = NULL;
   214     type->fields_ = NULL;
   215     type->newMap_ = NULL;
   216     type->returnType_ = returnType;
   217     type->parameters_ = parameters;
   218     type->defaults_ = defaults;
   219     type->variadicNative_ = variadic;
   220     return type;
   221 }
   222 
   223 bool
   224 Type::Compare(Type *left, Type *right)
   225 {
   226     if (left == right)
   227         return true;
   228 
   229     if (left->kind() != right->kind())
   230         return false;
   231 
   232     switch (left->kind()) {
   233       case Type::PRIMITIVE:
   234         return left->primitive() == right->primitive();
   235 
   236       case Type::ARRAY:
   237       {
   238         if (left->levels() != right->levels())
   239           return false;
   240         if (left->elements_ != right->elements_)
   241             return false;
   242         return Compare(left->contained(), right->contained());
   243       }
   244 
   245       case Type::FUNCTION:
   246       {
   247         if (!Compare(left->returnType(), right->returnType()))
   248             return false;
   249         if (left->parameters()->length() != right->parameters()->length())
   250             return false;
   251         if (left->isNative() != right->isNative())
   252             return false;
   253         if (left->isNative() && (left->isNativeVariadic() != right->isNativeVariadic()))
   254             return false;
   255         for (unsigned i = 0; i < left->parameters()->length(); i++) {
   256             Type *leftparam = left->parameterAt(i);
   257             Type *rightparam = right->parameterAt(i);
   258             if (!Compare(leftparam, rightparam))
   259                 return false;
   260         }
   261         return true;
   262       }
   263 
   264       case Type::ENUM:
   265         return false;
   266 
   267       case Type::VOID:
   268       	return true;
   269 
   270       default:
   271         assert(left->kind() == Type::REFERENCE);
   272         return Compare(left->contained(), right->contained());
   273     }
   274 }
   275 
   276 Descriptor *
   277 Type::lookupField(Handle<String> name, unsigned *index)
   278 {
   279     assert(isStruct());
   280 
   281     for (unsigned i = 0; i < fields_->length(); i++) {
   282         Descriptor *desc = Descriptor::cast(fields_->at(i));
   283         if (desc->name() == name) {
   284             *index = i;
   285             return desc;
   286         }
   287     }
   288 
   289     return NULL;
   290 }
   291