src/Types.cpp
author David Anderson <dvander@alliedmods.net>
Mon Dec 24 02:49:20 2012 -0800 (2012-12-24)
changeset 234 26e3035cdffc
parent 233 bbb498ccb4ac
child 235 43287eef2fff
permissions -rw-r--r--
Get string literals working again.
     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->primitive_ = prim;
    59     return type;
    60 }
    61 
    62 ArrayType *
    63 ArrayType::New(Zone *zone, Handle<Type> contained, int elements)
    64 {
    65     if (contained->isArray() &&
    66         ArrayType::cast(contained)->levels() == MAX_ARRAY_DEPTH)
    67     {
    68         zone->reportError(Message_MaximumArrayDepth);
    69         return NULL;
    70     }
    71 
    72     Local<ArrayType> type(zone, ArrayType::cast(zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old)));
    73     if (!type)
    74         return NULL;
    75 
    76     type->kind_ = ARRAY;
    77     type->contained_ = contained;
    78     type->elements_ = elements;
    79     if (!contained->isArray())
    80         type->levels_ = 1;
    81     else
    82         type->levels_ = ArrayType::cast(contained)->levels() + 1;
    83     return type;
    84 }
    85 
    86 ArrayType *
    87 ArrayType::NewExternal(Zone *zone, Handle<Type> contained)
    88 {
    89     Local<ArrayType> type(zone, ArrayType::cast(zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old)));
    90     if (!type)
    91         return NULL;
    92 
    93     assert(contained->isPrimitive());
    94 
    95     type->kind_ = EXTERNAL_ARRAY;
    96     type->contained_ = contained;
    97     type->elements_ = DYNAMIC_ARRAY_SIZE;
    98     type->levels_ = 1;
    99     return type;
   100 }
   101 
   102 ReferenceType *
   103 ReferenceType::New(Zone *zone, Handle<Type> contained)
   104 {
   105     Local<ReferenceType> type(zone, ReferenceType::cast(zone->allocate(MapKind_ReferenceType, sizeof(ReferenceType), Heap::Tenure_Old)));
   106     if (!type)
   107         return NULL;
   108 
   109     type->kind_ = REFERENCE;
   110     type->const_ = false;
   111     type->contained_ = contained;
   112     return type;
   113 }
   114 
   115 EnumType *
   116 EnumType::New(Zone *zone, Handle<String> name)
   117 {
   118     Local<EnumType> type(zone, EnumType::cast(zone->allocate(MapKind_EnumType, sizeof(EnumType), Heap::Tenure_Old)));
   119     if (!type)
   120         return NULL;
   121 
   122     type->kind_ = ENUM;
   123     type->name_ = name;
   124     return type;
   125 }
   126 
   127 #if 0
   128 Type *
   129 Type::NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters,
   130                 Handle<FixedArray> defaults, bool variadic)
   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_ = NATIVE;
   137     type->contained_ = NULL;
   138     type->fields_ = NULL;
   139     type->newMap_ = NULL;
   140     type->returnType_ = returnType;
   141     type->parameters_ = parameters;
   142     type->defaults_ = defaults;
   143     type->variadicNative_ = variadic;
   144     return type;
   145 }
   146 #endif
   147 
   148 bool
   149 Type::Compare(Type *left, Type *right)
   150 {
   151     if (left == right)
   152         return true;
   153 
   154     if (left->kind() != right->kind())
   155         return false;
   156 
   157     switch (left->kind()) {
   158       case Type::PRIMITIVE:
   159         return left->primitive() == right->primitive();
   160 
   161       case Type::ARRAY:
   162       {
   163         ArrayType *aleft = ArrayType::cast(left);
   164         ArrayType *aright = ArrayType::cast(right);
   165         if (aleft->levels() != aright->levels())
   166             return false;
   167         if (aleft->isFixedLength() != aright->isFixedLength())
   168             return false;
   169         if (aleft->isFixedLength() && aleft->fixedLength() != aright->fixedLength())
   170             return false;
   171         return Compare(aleft->contained(), aright->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(ReferenceType::cast(left)->contained(), ReferenceType::cast(right)->contained());
   204     }
   205 }
   206 
   207 StructType *
   208 StructType::New(Zone *zone, Handle<String> name, Handle<FixedArray> fields)
   209 {
   210     Local<StructType> type(zone, StructType::cast(zone->allocate(MapKind_StructType, sizeof(StructType), Heap::Tenure_Old)));
   211     if (!type)
   212         return NULL;
   213 
   214     type->kind_ = STRUCT;
   215     type->newMap_ = NULL;
   216     type->fields_ = fields;
   217     type->name_ = name;
   218 
   219     // Fill in field offsets.
   220     StructureBufferBuilder builder;
   221     Local<Type> fieldType(zone);
   222     for (size_t i = 0; i < fields->length(); i++) {
   223         Descriptor *desc = Descriptor::cast(fields->at(i));
   224         fieldType = desc->type();
   225 
   226         unsigned offset;
   227         if (!builder.add(fieldType, &offset))
   228             return NULL;
   229         desc->setOffset(offset);
   230     }
   231 
   232     Local<StructMap> map(zone, StructMap::New(zone, builder, type));
   233     if (!map)
   234         return NULL;
   235 
   236     type->newMap_ = map;
   237 
   238     return type;
   239 }
   240 
   241 Descriptor *
   242 StructType::lookupField(Handle<String> name, unsigned *index)
   243 {
   244     for (unsigned i = 0; i < fields_->length(); i++) {
   245         Descriptor *desc = Descriptor::cast(fields_->at(i));
   246         if (desc->name() == name) {
   247             if (index)
   248                 *index = i;
   249             return desc;
   250         }
   251     }
   252 
   253     return NULL;
   254 }
   255 
   256 FunctionType *
   257 FunctionType::New(Zone *zone, Handle<String> name, TokenKind token)
   258 {
   259     Local<FunctionType> type(zone, FunctionType::cast(zone->allocate(MapKind_FunctionType, sizeof(FunctionType), Heap::Tenure_Old)));
   260     if (!type)
   261         return NULL;
   262 
   263     type->kind_ = FUNCTION;
   264     type->parameters_ = NULL;
   265     type->defaults_ = NULL;
   266     type->returnType_ = NULL;
   267     type->name_ = name;
   268     type->token_ = token;
   269     return type;
   270 }
   271 
   272 // :TODO: this leaks an interior pointer.
   273 const char *
   274 ke::GetTypeName(Type *type)
   275 {
   276     if (type->isArray())
   277         return "array";
   278     if (type->isFunction())
   279         return "function";
   280     if (type->isVoid())
   281         return "void";
   282     if (type->isEnum())
   283         return EnumType::cast(type)->name()->chars();
   284     if (type->isStruct())
   285         return StructType::cast(type)->name()->chars();
   286     if (type->isReference())
   287         type = ReferenceType::cast(type)->contained();
   288     switch (type->primitive()) {
   289       case PrimitiveType_Bool:
   290         return "bool";
   291       case PrimitiveType_Char:
   292         return "String";
   293       case PrimitiveType_Int32:
   294         return "int";
   295       case PrimitiveType_Float:
   296         return "Float";
   297       default:
   298         return "<unknown>";
   299     }
   300 }
   301