src/Types.cpp
author David Anderson <dvander@alliedmods.net>
Sat Nov 17 19:23:39 2012 -0800 (2012-11-17)
changeset 200 e0a601465746
parent 195 c1ba166f3fc4
child 209 5cbec15fadfe
permissions -rw-r--r--
Fix OS X build.
     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     return type;
    38 }
    39 
    40 Type *
    41 Type::NewUnchecked(Zone *zone)
    42 {
    43     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    44     if (!type)
    45         return NULL;
    46 
    47     type->kind_ = UNCHECKED;
    48     type->contained_ = NULL;
    49     return type;
    50 }
    51 
    52 Type *
    53 Type::NewPrimitive(Zone *zone, PrimitiveType prim)
    54 {
    55     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    56     if (!type)
    57         return NULL;
    58 
    59     type->kind_ = PRIMITIVE;
    60     type->name_ = NULL;
    61     type->contained_ = NULL;
    62     type->primitive_ = prim;
    63     return type;
    64 }
    65 
    66 Type *
    67 Type::NewArray(Zone *zone, Handle<Type> contained, int elements, bool isConst)
    68 {
    69     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    70     if (!type)
    71         return NULL;
    72 
    73     type->kind_ = ARRAY;
    74     type->name_ = NULL;
    75     type->contained_ = contained;
    76     type->elements_ = elements;
    77     if (!contained->isArray())
    78         type->levels_ = 1;
    79     else
    80         type->levels_ = contained->levels() + 1;
    81     type->const_ = isConst;
    82     return type;
    83 }
    84 
    85 Type *
    86 Type::NewExternalArray(Zone *zone, Handle<Type> contained)
    87 {
    88     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    89     if (!type)
    90         return NULL;
    91 
    92     assert(contained->isPrimitive());
    93 
    94     type->kind_ = EXTERNAL_ARRAY;
    95     type->name_ = NULL;
    96     type->contained_ = contained;
    97     type->elements_ = DYNAMIC_ARRAY_SIZE;
    98     type->levels_ = 1;
    99     type->const_ = false;
   100     return type;
   101 }
   102 
   103 Type *
   104 Type::NewReference(Zone *zone, Handle<Type> contained, bool isConst)
   105 {
   106     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   107     if (!type)
   108         return NULL;
   109 
   110     type->kind_ = REFERENCE;
   111     type->name_ = NULL;
   112     type->contained_ = contained;
   113     type->const_ = isConst;
   114     return type;
   115 }
   116 
   117 Type *
   118 Type::NewEnum(Zone *zone, Handle<String> name)
   119 {
   120     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   121     if (!type)
   122         return NULL;
   123 
   124     type->kind_ = ENUM;
   125     type->name_ = name;
   126     type->contained_ = NULL;
   127     return type;
   128 }
   129 
   130 #if 0
   131 Type *
   132 Type::NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters,
   133                 Handle<FixedArray> defaults, bool variadic)
   134 {
   135     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   136     if (!type)
   137         return NULL;
   138 
   139     type->kind_ = NATIVE;
   140     type->name_ = NULL;
   141     type->contained_ = NULL;
   142     type->fields_ = NULL;
   143     type->newMap_ = NULL;
   144     type->returnType_ = returnType;
   145     type->parameters_ = parameters;
   146     type->defaults_ = defaults;
   147     type->variadicNative_ = variadic;
   148     return type;
   149 }
   150 #endif
   151 
   152 bool
   153 Type::Compare(Type *left, Type *right)
   154 {
   155     if (left == right)
   156         return true;
   157 
   158     if (left->kind() != right->kind())
   159         return false;
   160 
   161     switch (left->kind()) {
   162       case Type::PRIMITIVE:
   163         return left->primitive() == right->primitive();
   164 
   165       case Type::ARRAY:
   166       {
   167         if (left->levels() != right->levels())
   168           return false;
   169         if (left->elements_ != right->elements_)
   170             return false;
   171         return Compare(left->contained(), right->contained());
   172       }
   173 
   174       case Type::FUNCTION:
   175       {
   176         FunctionType *fleft = FunctionType::cast(left);
   177         FunctionType *fright = FunctionType::cast(right);
   178         if (!Compare(fleft->returnType(), fright->returnType()))
   179             return false;
   180         if (fleft->parameters()->length() != fright->parameters()->length())
   181             return false;
   182         if (fleft->isNative() != fright->isNative())
   183             return false;
   184         if (fleft->isNative() && (fleft->isNativeVariadic() != fright->isNativeVariadic()))
   185             return false;
   186         for (unsigned i = 0; i < fleft->parameters()->length(); i++) {
   187             Type *leftparam = fleft->parameterAt(i);
   188             Type *rightparam = fright->parameterAt(i);
   189             if (!Compare(leftparam, rightparam))
   190                 return false;
   191         }
   192         return true;
   193       }
   194 
   195       case Type::ENUM:
   196         return false;
   197 
   198       case Type::VOID:
   199       	return true;
   200 
   201       default:
   202         assert(left->kind() == Type::REFERENCE);
   203         return Compare(left->contained(), right->contained());
   204     }
   205 }
   206 
   207 
   208 StructType *
   209 StructType::New(Zone *zone, Handle<String> name, Handle<FixedArray> fields)
   210 {
   211     Local<StructType> type(zone, StructType::cast(zone->allocate(MapKind_StructType, sizeof(StructType), Heap::Tenure_Old)));
   212     if (!type)
   213         return NULL;
   214 
   215     type->kind_ = STRUCT;
   216     type->name_ = name;
   217     type->contained_ = NULL;
   218     type->newMap_ = NULL;
   219     type->fields_ = fields;
   220 
   221     // Fill in field offsets.
   222     StructureBufferBuilder builder;
   223     Local<Type> fieldType(zone);
   224     for (size_t i = 0; i < fields->length(); i++) {
   225         Descriptor *desc = Descriptor::cast(fields->at(i));
   226         fieldType = desc->type();
   227 
   228         unsigned offset;
   229         if (!builder.add(fieldType, &offset))
   230             return NULL;
   231         desc->setOffset(offset);
   232     }
   233 
   234     Local<StructMap> map(zone, StructMap::New(zone, builder, type));
   235     if (!map)
   236         return NULL;
   237 
   238     type->newMap_ = map;
   239 
   240     return type;
   241 }
   242 
   243 Descriptor *
   244 StructType::lookupField(Handle<String> name, unsigned *index)
   245 {
   246     for (unsigned i = 0; i < fields_->length(); i++) {
   247         Descriptor *desc = Descriptor::cast(fields_->at(i));
   248         if (desc->name() == name) {
   249             if (index)
   250                 *index = i;
   251             return desc;
   252         }
   253     }
   254 
   255     return NULL;
   256 }
   257 
   258 FunctionType *
   259 FunctionType::New(Zone *zone, TokenKind token)
   260 {
   261     Local<FunctionType> type(zone, FunctionType::cast(zone->allocate(MapKind_FunctionType, sizeof(FunctionType), Heap::Tenure_Old)));
   262     if (!type)
   263         return NULL;
   264 
   265     type->kind_ = FUNCTION;
   266     type->name_ = NULL;
   267     type->contained_ = NULL;
   268     type->parameters_ = NULL;
   269     type->defaults_ = NULL;
   270     type->returnType_ = NULL;
   271     type->token_ = token;
   272     return type;
   273 }
   274 
   275 // :TODO: this leaks an interior pointer.
   276 const char *
   277 ke::GetTypeName(Type *type)
   278 {
   279     if (type->isArray())
   280         return "array";
   281     if (type->isFunction())
   282         return "function";
   283     if (type->isVoid())
   284         return "void";
   285     if (type->isEnum() || type->isStruct())
   286         return type->name()->chars();
   287     if (type->isReference())
   288         type = type->contained();
   289     switch (type->primitive()) {
   290       case PrimitiveType_Bool:
   291         return "bool";
   292       case PrimitiveType_Char:
   293         return "String";
   294       case PrimitiveType_Int32:
   295         return "int";
   296       case PrimitiveType_Float:
   297         return "Float";
   298       default:
   299         return "<unknown>";
   300     }
   301 }
   302