src/Types.cpp
author David Anderson <dvander@alliedmods.net>
Sat Sep 15 19:33:24 2012 -0700 (2012-09-15)
changeset 186 03a663e96860
parent 184 387d76b1e981
child 188 bab29bcec7fe
permissions -rw-r--r--
Allow more empty array creation.
     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::NewReference(Zone *zone, Handle<Type> contained, bool isConst)
   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     type->kind_ = REFERENCE;
   114     type->name_ = NULL;
   115     type->contained_ = contained;
   116     type->returnType_ = NULL;
   117     type->parameters_ = NULL;
   118     type->defaults_ = NULL;
   119     type->fields_ = NULL;
   120     type->newMap_ = NULL;
   121     type->const_ = isConst;
   122     return type;
   123 }
   124 
   125 Type *
   126 Type::NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters,
   127                   Handle<FixedArray> defaults)
   128 {
   129     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   130     if (!type)
   131         return NULL;
   132 
   133     type->kind_ = FUNCTION;
   134     type->name_ = NULL;
   135     type->contained_ = NULL;
   136     type->fields_ = NULL;
   137     type->newMap_ = NULL;
   138     type->returnType_ = returnType;
   139     type->parameters_ = parameters;
   140     type->defaults_ = defaults;
   141     return type;
   142 }
   143 
   144 Type *
   145 Type::NewEnum(Zone *zone, Handle<String> name)
   146 {
   147     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   148     if (!type)
   149         return NULL;
   150 
   151     type->kind_ = ENUM;
   152     type->name_ = name;
   153     type->contained_ = NULL;
   154     type->returnType_ = NULL;
   155     type->parameters_ = NULL;
   156     type->defaults_ = NULL;
   157     type->fields_ = NULL;
   158     type->newMap_ = NULL;
   159     return type;
   160 }
   161 
   162 Type *
   163 Type::NewStruct(Zone *zone, Handle<String> name, Handle<FixedArray> fields, Handle<Map> newMap)
   164 {
   165     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   166     if (!type)
   167         return NULL;
   168 
   169     type->kind_ = STRUCT;
   170     type->name_ = name;
   171     type->contained_ = NULL;
   172     type->returnType_ = NULL;
   173     type->parameters_ = NULL;
   174     type->defaults_ = NULL;
   175     type->newMap_ = newMap;
   176     type->fields_ = fields;
   177     return type;
   178 }
   179 
   180 Type *
   181 Type::NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters,
   182                 Handle<FixedArray> defaults, bool variadic)
   183 {
   184     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   185     if (!type)
   186         return NULL;
   187 
   188     type->kind_ = NATIVE;
   189     type->name_ = NULL;
   190     type->contained_ = NULL;
   191     type->fields_ = NULL;
   192     type->newMap_ = NULL;
   193     type->returnType_ = returnType;
   194     type->parameters_ = parameters;
   195     type->defaults_ = defaults;
   196     type->variadicNative_ = variadic;
   197     return type;
   198 }
   199 
   200 bool
   201 Type::Compare(Type *left, Type *right)
   202 {
   203     if (left == right)
   204         return true;
   205 
   206     if (left->kind() != right->kind())
   207         return false;
   208 
   209     switch (left->kind()) {
   210       case Type::PRIMITIVE:
   211         return left->primitive() == right->primitive();
   212 
   213       case Type::ARRAY:
   214       {
   215         if (left->levels() != right->levels())
   216           return false;
   217         if (left->elements_ != right->elements_)
   218             return false;
   219         return Compare(left->contained(), right->contained());
   220       }
   221 
   222       case Type::FUNCTION:
   223       {
   224         if (!Compare(left->returnType(), right->returnType()))
   225             return false;
   226         if (left->parameters()->length() != right->parameters()->length())
   227             return false;
   228         if (left->isNative() != right->isNative())
   229             return false;
   230         if (left->isNative() && (left->isNativeVariadic() != right->isNativeVariadic()))
   231             return false;
   232         for (unsigned i = 0; i < left->parameters()->length(); i++) {
   233             Type *leftparam = left->parameterAt(i);
   234             Type *rightparam = right->parameterAt(i);
   235             if (!Compare(leftparam, rightparam))
   236                 return false;
   237         }
   238         return true;
   239       }
   240 
   241       case Type::ENUM:
   242         return false;
   243 
   244       case Type::VOID:
   245       	return true;
   246 
   247       default:
   248         assert(left->kind() == Type::REFERENCE);
   249         return Compare(left->contained(), right->contained());
   250     }
   251 }
   252 
   253 Descriptor *
   254 Type::lookupField(Handle<String> name, unsigned *index)
   255 {
   256     assert(isStruct());
   257 
   258     for (unsigned i = 0; i < fields_->length(); i++) {
   259         Descriptor *desc = Descriptor::cast(fields_->at(i));
   260         if (desc->name() == name) {
   261             *index = i;
   262             return desc;
   263         }
   264     }
   265 
   266     return NULL;
   267 }
   268