src/Types.cpp
author David Anderson <dvander@alliedmods.net>
Sat Aug 04 17:51:43 2012 -0700 (2012-08-04)
changeset 146 dc7d3b7a918c
parent 145 e9d804821c48
child 147 9c544823d090
permissions -rw-r--r--
Basic support for parsing and creating types from structure syntax.
     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 "Heap-inl.h"
    24 
    25 using namespace ke;
    26 
    27 Type *
    28 Type::NewVoid(Zone *zone)
    29 {
    30     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    31     if (!type)
    32         return NULL;
    33 
    34     type->kind_ = VOID;
    35     type->contained_ = NULL;
    36     type->returnType_ = NULL;
    37     type->parameters_ = NULL;
    38     type->fields_ = NULL;
    39     return type;
    40 }
    41 
    42 Type *
    43 Type::NewPrimitive(Zone *zone, PrimitiveType prim)
    44 {
    45     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    46     if (!type)
    47         return NULL;
    48 
    49     type->kind_ = PRIMITIVE;
    50     type->name_ = NULL;
    51     type->contained_ = NULL;
    52     type->returnType_ = NULL;
    53     type->parameters_ = NULL;
    54     type->fields_ = NULL;
    55     type->primitive_ = prim;
    56     return type;
    57 }
    58 
    59 Type *
    60 Type::NewArray(Zone *zone, Handle<Type> contained, int elements, bool isConst)
    61 {
    62     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    63     if (!type)
    64         return NULL;
    65 
    66     type->kind_ = ARRAY;
    67     type->name_ = NULL;
    68     type->contained_ = contained;
    69     type->returnType_ = NULL;
    70     type->parameters_ = NULL;
    71     type->fields_ = NULL;
    72     type->elements_ = elements;
    73     if (!contained->isArray())
    74         type->levels_ = 1;
    75     else
    76         type->levels_ = contained->levels() + 1;
    77     type->const_ = isConst;
    78     return type;
    79 }
    80 
    81 Type *
    82 Type::NewReference(Zone *zone, Handle<Type> contained, bool isConst)
    83 {
    84     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    85     if (!type)
    86         return NULL;
    87 
    88     type->kind_ = REFERENCE;
    89     type->name_ = NULL;
    90     type->contained_ = contained;
    91     type->returnType_ = NULL;
    92     type->parameters_ = NULL;
    93     type->fields_ = NULL;
    94     type->const_ = isConst;
    95     return type;
    96 }
    97 
    98 Type *
    99 Type::NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters)
   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_ = FUNCTION;
   106     type->name_ = NULL;
   107     type->contained_ = NULL;
   108     type->fields_ = NULL;
   109     type->returnType_ = returnType;
   110     type->parameters_ = parameters;
   111     return type;
   112 }
   113 
   114 Type *
   115 Type::NewEnum(Zone *zone, Handle<String> name)
   116 {
   117     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   118     if (!type)
   119         return NULL;
   120 
   121     type->kind_ = ENUM;
   122     type->name_ = name;
   123     type->contained_ = NULL;
   124     type->returnType_ = NULL;
   125     type->parameters_ = NULL;
   126     type->fields_ = NULL;
   127     return type;
   128 }
   129 
   130 Type *
   131 Type::NewStruct(Zone *zone, Handle<String> name, Handle<FixedArray> fields)
   132 {
   133     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   134     if (!type)
   135         return NULL;
   136 
   137     type->kind_ = STRUCT;
   138     type->name_ = name;
   139     type->contained_ = NULL;
   140     type->returnType_ = NULL;
   141     type->parameters_ = NULL;
   142     type->fields_ = fields;
   143     return type;
   144 }
   145 
   146 Type *
   147 Type::NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters, bool variadic)
   148 {
   149     Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   150     if (!type)
   151         return NULL;
   152 
   153     type->kind_ = NATIVE;
   154     type->name_ = NULL;
   155     type->contained_ = NULL;
   156     type->fields_ = NULL;
   157     type->returnType_ = returnType;
   158     type->parameters_ = parameters;
   159     type->variadicNative_ = variadic;
   160     return type;
   161 }
   162 
   163 bool
   164 Type::Compare(Type *left, Type *right)
   165 {
   166     if (left == right)
   167         return true;
   168 
   169     if (left->kind() != right->kind())
   170         return false;
   171 
   172     switch (left->kind()) {
   173       case Type::PRIMITIVE:
   174         return left->primitive() == right->primitive();
   175 
   176       case Type::ARRAY:
   177       {
   178         if (left->levels() != right->levels())
   179           return false;
   180         if (left->elements() != right->elements())
   181           return false;
   182         return Compare(left->contained(), right->contained());
   183       }
   184 
   185       case Type::FUNCTION:
   186       {
   187         if (!Compare(left->returnType(), right->returnType()))
   188             return false;
   189         if (left->parameters()->length() != right->parameters()->length())
   190             return false;
   191         if (left->isNative() != right->isNative())
   192             return false;
   193         if (left->isNative() && (left->isNativeVariadic() != right->isNativeVariadic()))
   194             return false;
   195         for (unsigned i = 0; i < left->parameters()->length(); i++) {
   196             Type *leftparam = left->parameterAt(i);
   197             Type *rightparam = right->parameterAt(i);
   198             if (!Compare(leftparam, rightparam))
   199                 return false;
   200         }
   201         return true;
   202       }
   203 
   204       case Type::ENUM:
   205         return false;
   206 
   207       case Type::VOID:
   208       	return true;
   209 
   210       default:
   211         assert(left->kind() == Type::REFERENCE);
   212         return Compare(left->contained(), right->contained());
   213     }
   214 }