dvander@143: /* vim: set ts=4 sw=4 tw=99 et: dvander@143: * dvander@0: * Copyright (C) 2012 David Anderson dvander@0: * dvander@143: * This file is part of SourcePawn. dvander@0: * dvander@143: * SourcePawn is free software: you can redistribute it and/or modify it under dvander@0: * the terms of the GNU General Public License as published by the Free dvander@0: * Software Foundation, either version 3 of the License, or (at your option) dvander@0: * any later version. dvander@0: * dvander@143: * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY dvander@0: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@0: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@0: * dvander@0: * You should have received a copy of the GNU General Public License along with dvander@143: * SourcePawn. If not, see http://www.gnu.org/licenses/. dvander@0: */ danderson@92: #include dvander@0: #include "Types.h" dvander@11: #include "Zone.h" dvander@54: #include "Strings.h" dvander@148: #include "Structures.h" dvander@11: #include "Heap-inl.h" dvander@0: dvander@59: using namespace ke; dvander@0: dvander@11: Type * dvander@71: Type::NewVoid(Zone *zone) dvander@71: { dvander@71: Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); dvander@71: if (!type) dvander@71: return NULL; dvander@71: dvander@71: type->kind_ = VOID; dvander@71: type->contained_ = NULL; dvander@71: type->returnType_ = NULL; dvander@71: type->parameters_ = NULL; dvander@168: type->defaults_ = NULL; dvander@146: type->fields_ = NULL; dvander@147: type->newMap_ = NULL; dvander@71: return type; dvander@71: } dvander@71: dvander@71: Type * dvander@167: Type::NewUnchecked(Zone *zone) dvander@167: { dvander@167: Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); dvander@167: if (!type) dvander@167: return NULL; dvander@167: dvander@167: type->kind_ = UNCHECKED; dvander@167: type->contained_ = NULL; dvander@167: type->returnType_ = NULL; dvander@167: type->parameters_ = NULL; dvander@168: type->defaults_ = NULL; dvander@167: type->fields_ = NULL; dvander@167: type->newMap_ = NULL; dvander@167: return type; dvander@167: } dvander@167: dvander@167: Type * dvander@12: Type::NewPrimitive(Zone *zone, PrimitiveType prim) dvander@12: { dvander@41: Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); dvander@41: if (!type) dvander@12: return NULL; dvander@12: dvander@13: type->kind_ = PRIMITIVE; dvander@145: type->name_ = NULL; dvander@13: type->contained_ = NULL; dvander@53: type->returnType_ = NULL; dvander@53: type->parameters_ = NULL; dvander@168: type->defaults_ = NULL; dvander@146: type->fields_ = NULL; dvander@147: type->newMap_ = NULL; dvander@147: type->newMap_ = NULL; dvander@13: type->primitive_ = prim; dvander@12: return type; dvander@12: } dvander@12: dvander@12: Type * dvander@41: Type::NewArray(Zone *zone, Handle contained, int elements, bool isConst) dvander@4: { dvander@41: Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); dvander@41: if (!type) dvander@11: return NULL; dvander@11: dvander@14: type->kind_ = ARRAY; dvander@145: type->name_ = NULL; dvander@13: type->contained_ = contained; dvander@53: type->returnType_ = NULL; dvander@53: type->parameters_ = NULL; dvander@168: type->defaults_ = NULL; dvander@146: type->fields_ = NULL; dvander@147: type->newMap_ = NULL; dvander@13: type->elements_ = elements; dvander@145: if (!contained->isArray()) dvander@13: type->levels_ = 1; dvander@13: else dvander@13: type->levels_ = contained->levels() + 1; dvander@21: type->const_ = isConst; dvander@0: return type; dvander@0: } dvander@14: dvander@14: Type * dvander@67: Type::NewReference(Zone *zone, Handle contained, bool isConst) dvander@14: { dvander@41: Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); dvander@41: if (!type) dvander@14: return NULL; dvander@14: dvander@14: type->kind_ = REFERENCE; dvander@145: type->name_ = NULL; dvander@14: type->contained_ = contained; dvander@53: type->returnType_ = NULL; dvander@53: type->parameters_ = NULL; dvander@168: type->defaults_ = NULL; dvander@146: type->fields_ = NULL; dvander@147: type->newMap_ = NULL; dvander@67: type->const_ = isConst; dvander@14: return type; dvander@14: } dvander@14: dvander@14: Type * dvander@168: Type::NewFunction(Zone *zone, Handle returnType, Handle parameters, dvander@168: Handle defaults) dvander@14: { dvander@41: Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); dvander@41: if (!type) dvander@14: return NULL; dvander@14: dvander@14: type->kind_ = FUNCTION; dvander@145: type->name_ = NULL; dvander@53: type->contained_ = NULL; dvander@146: type->fields_ = NULL; dvander@147: type->newMap_ = NULL; dvander@25: type->returnType_ = returnType; dvander@14: type->parameters_ = parameters; dvander@168: type->defaults_ = defaults; dvander@14: return type; dvander@14: } dvander@63: dvander@68: Type * dvander@145: Type::NewEnum(Zone *zone, Handle name) dvander@145: { dvander@145: Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); dvander@145: if (!type) dvander@145: return NULL; dvander@145: dvander@145: type->kind_ = ENUM; dvander@145: type->name_ = name; dvander@145: type->contained_ = NULL; dvander@145: type->returnType_ = NULL; dvander@145: type->parameters_ = NULL; dvander@168: type->defaults_ = NULL; dvander@146: type->fields_ = NULL; dvander@147: type->newMap_ = NULL; dvander@146: return type; dvander@146: } dvander@146: dvander@146: Type * dvander@147: Type::NewStruct(Zone *zone, Handle name, Handle fields, Handle newMap) dvander@146: { dvander@146: Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); dvander@146: if (!type) dvander@146: return NULL; dvander@146: dvander@146: type->kind_ = STRUCT; dvander@146: type->name_ = name; dvander@146: type->contained_ = NULL; dvander@146: type->returnType_ = NULL; dvander@146: type->parameters_ = NULL; dvander@168: type->defaults_ = NULL; dvander@147: type->newMap_ = newMap; dvander@146: type->fields_ = fields; dvander@145: return type; dvander@145: } dvander@145: dvander@145: Type * dvander@168: Type::NewNative(Zone *zone, Handle returnType, Handle parameters, dvander@168: Handle defaults, bool variadic) dvander@68: { dvander@68: Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); dvander@68: if (!type) dvander@68: return NULL; dvander@68: dvander@68: type->kind_ = NATIVE; dvander@145: type->name_ = NULL; dvander@68: type->contained_ = NULL; dvander@146: type->fields_ = NULL; dvander@147: type->newMap_ = NULL; dvander@68: type->returnType_ = returnType; dvander@68: type->parameters_ = parameters; dvander@168: type->defaults_ = defaults; dvander@68: type->variadicNative_ = variadic; dvander@68: return type; dvander@68: } dvander@68: dvander@63: bool dvander@63: Type::Compare(Type *left, Type *right) dvander@63: { dvander@145: if (left == right) dvander@145: return true; dvander@145: dvander@63: if (left->kind() != right->kind()) dvander@63: return false; dvander@63: dvander@63: switch (left->kind()) { dvander@63: case Type::PRIMITIVE: dvander@145: return left->primitive() == right->primitive(); dvander@63: dvander@63: case Type::ARRAY: dvander@63: { dvander@63: if (left->levels() != right->levels()) dvander@63: return false; dvander@63: if (left->elements() != right->elements()) dvander@63: return false; dvander@63: return Compare(left->contained(), right->contained()); dvander@63: } dvander@63: dvander@63: case Type::FUNCTION: dvander@63: { dvander@63: if (!Compare(left->returnType(), right->returnType())) dvander@63: return false; dvander@63: if (left->parameters()->length() != right->parameters()->length()) dvander@63: return false; dvander@69: if (left->isNative() != right->isNative()) dvander@69: return false; dvander@69: if (left->isNative() && (left->isNativeVariadic() != right->isNativeVariadic())) dvander@69: return false; dvander@63: for (unsigned i = 0; i < left->parameters()->length(); i++) { dvander@63: Type *leftparam = left->parameterAt(i); dvander@63: Type *rightparam = right->parameterAt(i); dvander@63: if (!Compare(leftparam, rightparam)) dvander@63: return false; dvander@63: } dvander@63: return true; dvander@63: } dvander@63: dvander@145: case Type::ENUM: dvander@145: return false; dvander@145: dvander@124: case Type::VOID: dvander@124: return true; dvander@124: dvander@63: default: dvander@63: assert(left->kind() == Type::REFERENCE); dvander@63: return Compare(left->contained(), right->contained()); dvander@63: } dvander@63: } dvander@148: dvander@148: Descriptor * dvander@148: Type::lookupField(Handle name, unsigned *index) dvander@148: { dvander@148: assert(isStruct()); dvander@148: dvander@148: for (unsigned i = 0; i < fields_->length(); i++) { dvander@148: Descriptor *desc = Descriptor::cast(fields_->at(i)); dvander@148: if (desc->name() == name) { dvander@148: *index = i; dvander@148: return desc; dvander@148: } dvander@148: } dvander@148: dvander@148: return NULL; dvander@148: } dvander@148: