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