src/Types.cpp
author David Anderson <dvander@alliedmods.net>
Sat Aug 04 20:12:20 2012 -0700 (2012-08-04)
changeset 148 c0740249963c
parent 147 9c544823d090
child 167 cf82769eb136
permissions -rw-r--r--
All but interpreter support for getting and setting struct fields.
     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->fields_ = NULL;
    40     type->newMap_ = NULL;
    41     return type;
    42 }
    43 
    44 Type *
    45 Type::NewPrimitive(Zone *zone, PrimitiveType prim)
    46 {
    47     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    48     if (!type)
    49         return NULL;
    50 
    51     type->kind_ = PRIMITIVE;
    52     type->name_ = NULL;
    53     type->contained_ = NULL;
    54     type->returnType_ = NULL;
    55     type->parameters_ = NULL;
    56     type->fields_ = NULL;
    57     type->newMap_ = NULL;
    58     type->newMap_ = NULL;
    59     type->primitive_ = prim;
    60     return type;
    61 }
    62 
    63 Type *
    64 Type::NewArray(Zone *zone, Handle<Type> contained, int elements, bool isConst)
    65 {
    66     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    67     if (!type)
    68         return NULL;
    69 
    70     type->kind_ = ARRAY;
    71     type->name_ = NULL;
    72     type->contained_ = contained;
    73     type->returnType_ = NULL;
    74     type->parameters_ = NULL;
    75     type->fields_ = NULL;
    76     type->newMap_ = NULL;
    77     type->elements_ = elements;
    78     if (!contained->isArray())
    79         type->levels_ = 1;
    80     else
    81         type->levels_ = contained->levels() + 1;
    82     type->const_ = isConst;
    83     return type;
    84 }
    85 
    86 Type *
    87 Type::NewReference(Zone *zone, Handle<Type> contained, bool isConst)
    88 {
    89     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    90     if (!type)
    91         return NULL;
    92 
    93     type->kind_ = REFERENCE;
    94     type->name_ = NULL;
    95     type->contained_ = contained;
    96     type->returnType_ = NULL;
    97     type->parameters_ = NULL;
    98     type->fields_ = NULL;
    99     type->newMap_ = NULL;
   100     type->const_ = isConst;
   101     return type;
   102 }
   103 
   104 Type *
   105 Type::NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters)
   106 {
   107     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   108     if (!type)
   109         return NULL;
   110 
   111     type->kind_ = FUNCTION;
   112     type->name_ = NULL;
   113     type->contained_ = NULL;
   114     type->fields_ = NULL;
   115     type->newMap_ = NULL;
   116     type->returnType_ = returnType;
   117     type->parameters_ = parameters;
   118     return type;
   119 }
   120 
   121 Type *
   122 Type::NewEnum(Zone *zone, Handle<String> name)
   123 {
   124     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   125     if (!type)
   126         return NULL;
   127 
   128     type->kind_ = ENUM;
   129     type->name_ = name;
   130     type->contained_ = NULL;
   131     type->returnType_ = NULL;
   132     type->parameters_ = NULL;
   133     type->fields_ = NULL;
   134     type->newMap_ = NULL;
   135     return type;
   136 }
   137 
   138 Type *
   139 Type::NewStruct(Zone *zone, Handle<String> name, Handle<FixedArray> fields, Handle<Map> newMap)
   140 {
   141     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   142     if (!type)
   143         return NULL;
   144 
   145     type->kind_ = STRUCT;
   146     type->name_ = name;
   147     type->contained_ = NULL;
   148     type->returnType_ = NULL;
   149     type->parameters_ = NULL;
   150     type->newMap_ = newMap;
   151     type->fields_ = fields;
   152     return type;
   153 }
   154 
   155 Type *
   156 Type::NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters, bool variadic)
   157 {
   158     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   159     if (!type)
   160         return NULL;
   161 
   162     type->kind_ = NATIVE;
   163     type->name_ = NULL;
   164     type->contained_ = NULL;
   165     type->fields_ = NULL;
   166     type->newMap_ = NULL;
   167     type->returnType_ = returnType;
   168     type->parameters_ = parameters;
   169     type->variadicNative_ = variadic;
   170     return type;
   171 }
   172 
   173 bool
   174 Type::Compare(Type *left, Type *right)
   175 {
   176     if (left == right)
   177         return true;
   178 
   179     if (left->kind() != right->kind())
   180         return false;
   181 
   182     switch (left->kind()) {
   183       case Type::PRIMITIVE:
   184         return left->primitive() == right->primitive();
   185 
   186       case Type::ARRAY:
   187       {
   188         if (left->levels() != right->levels())
   189           return false;
   190         if (left->elements() != right->elements())
   191           return false;
   192         return Compare(left->contained(), right->contained());
   193       }
   194 
   195       case Type::FUNCTION:
   196       {
   197         if (!Compare(left->returnType(), right->returnType()))
   198             return false;
   199         if (left->parameters()->length() != right->parameters()->length())
   200             return false;
   201         if (left->isNative() != right->isNative())
   202             return false;
   203         if (left->isNative() && (left->isNativeVariadic() != right->isNativeVariadic()))
   204             return false;
   205         for (unsigned i = 0; i < left->parameters()->length(); i++) {
   206             Type *leftparam = left->parameterAt(i);
   207             Type *rightparam = right->parameterAt(i);
   208             if (!Compare(leftparam, rightparam))
   209                 return false;
   210         }
   211         return true;
   212       }
   213 
   214       case Type::ENUM:
   215         return false;
   216 
   217       case Type::VOID:
   218       	return true;
   219 
   220       default:
   221         assert(left->kind() == Type::REFERENCE);
   222         return Compare(left->contained(), right->contained());
   223     }
   224 }
   225 
   226 Descriptor *
   227 Type::lookupField(Handle<String> name, unsigned *index)
   228 {
   229     assert(isStruct());
   230 
   231     for (unsigned i = 0; i < fields_->length(); i++) {
   232         Descriptor *desc = Descriptor::cast(fields_->at(i));
   233         if (desc->name() == name) {
   234             *index = i;
   235             return desc;
   236         }
   237     }
   238 
   239     return NULL;
   240 }
   241