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@238: void dvander@240: Type::init(Kind kind, Type *root) dvander@238: { dvander@238: this->kind_ = kind; dvander@240: this->root_ = root ? root : this; dvander@238: } dvander@238: 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@238: type->init(VOID); dvander@71: return type; dvander@71: } dvander@71: dvander@71: Type * dvander@235: Type::NewString(Zone *zone) dvander@235: { dvander@235: Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); dvander@235: if (!type) dvander@235: return NULL; dvander@235: dvander@238: type->init(STRING); dvander@235: return type; dvander@235: } dvander@235: dvander@235: 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@238: type->init(UNCHECKED); 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@238: type->init(PRIMITIVE); dvander@233: type->primitive_ = prim; dvander@12: return type; dvander@12: } dvander@12: dvander@240: Type * dvander@240: Type::NewQualified(Zone *zone, TypeQualifiers qual, Handle root) dvander@240: { dvander@240: Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); dvander@240: if (!type) dvander@240: return NULL; dvander@240: dvander@240: type->init(QUALTYPE, root); dvander@240: type->quals_ = qual; dvander@240: return type; dvander@240: } dvander@240: dvander@209: ArrayType * dvander@209: ArrayType::New(Zone *zone, Handle contained, int elements) dvander@4: { dvander@212: if (contained->isArray() && dvander@212: ArrayType::cast(contained)->levels() == MAX_ARRAY_DEPTH) dvander@212: { dvander@212: zone->reportError(Message_MaximumArrayDepth); dvander@212: return NULL; dvander@212: } dvander@212: dvander@239: Local type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old)); dvander@41: if (!type) dvander@11: return NULL; dvander@11: dvander@238: type->init(ARRAY); dvander@13: type->contained_ = contained; dvander@13: type->elements_ = elements; dvander@145: if (!contained->isArray()) dvander@13: type->levels_ = 1; dvander@13: else dvander@209: type->levels_ = ArrayType::cast(contained)->levels() + 1; dvander@0: return type; dvander@0: } dvander@14: dvander@209: ArrayType * dvander@209: ArrayType::NewExternal(Zone *zone, Handle contained) dvander@188: { dvander@239: Local type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old)); dvander@188: if (!type) dvander@188: return NULL; dvander@188: dvander@188: assert(contained->isPrimitive()); dvander@188: dvander@238: type->init(EXTERNAL_ARRAY); dvander@188: type->contained_ = contained; dvander@188: type->elements_ = DYNAMIC_ARRAY_SIZE; dvander@188: type->levels_ = 1; dvander@188: return type; dvander@188: } dvander@188: dvander@222: ReferenceType * dvander@222: ReferenceType::New(Zone *zone, Handle contained) dvander@14: { dvander@239: Local type(zone, (ReferenceType *)zone->allocate(MapKind_ReferenceType, sizeof(ReferenceType), Heap::Tenure_Old)); dvander@41: if (!type) dvander@14: return NULL; dvander@14: dvander@238: type->init(REFERENCE); dvander@222: type->contained_ = contained; dvander@14: return type; dvander@14: } dvander@14: dvander@233: EnumType * dvander@233: EnumType::New(Zone *zone, Handle name) dvander@145: { dvander@239: Local type(zone, (EnumType *)zone->allocate(MapKind_EnumType, sizeof(EnumType), Heap::Tenure_Old)); dvander@145: if (!type) dvander@145: return NULL; dvander@145: dvander@238: type->init(ENUM); dvander@145: type->name_ = name; dvander@146: return type; dvander@146: } dvander@146: dvander@195: StructType * dvander@195: StructType::New(Zone *zone, Handle name, Handle fields) dvander@148: { dvander@239: Local type(zone, (StructType *)zone->allocate(MapKind_StructType, sizeof(StructType), Heap::Tenure_Old)); dvander@195: if (!type) dvander@195: return NULL; dvander@195: dvander@238: type->init(STRUCT); dvander@195: type->newMap_ = NULL; dvander@195: type->fields_ = fields; dvander@233: type->name_ = name; dvander@195: dvander@195: // Fill in field offsets. dvander@195: StructureBufferBuilder builder; dvander@195: Local fieldType(zone); dvander@195: for (size_t i = 0; i < fields->length(); i++) { dvander@195: Descriptor *desc = Descriptor::cast(fields->at(i)); dvander@195: fieldType = desc->type(); dvander@148: dvander@195: unsigned offset; dvander@195: if (!builder.add(fieldType, &offset)) dvander@195: return NULL; dvander@195: desc->setOffset(offset); dvander@195: } dvander@195: dvander@195: Local map(zone, StructMap::New(zone, builder, type)); dvander@195: if (!map) dvander@195: return NULL; dvander@195: dvander@195: type->newMap_ = map; dvander@195: dvander@195: return type; dvander@195: } dvander@195: dvander@195: Descriptor * dvander@195: StructType::lookupField(Handle name, unsigned *index) dvander@195: { 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@195: if (index) dvander@195: *index = i; dvander@148: return desc; dvander@148: } dvander@148: } dvander@148: dvander@148: return NULL; dvander@148: } dvander@148: dvander@195: FunctionType * dvander@233: FunctionType::New(Zone *zone, Handle name, TokenKind token) dvander@195: { dvander@239: Local type(zone, (FunctionType *)zone->allocate(MapKind_FunctionType, sizeof(FunctionType), Heap::Tenure_Old)); dvander@195: if (!type) dvander@195: return NULL; dvander@195: dvander@238: type->init(FUNCTION); dvander@195: type->parameters_ = NULL; dvander@195: type->defaults_ = NULL; dvander@195: type->returnType_ = NULL; dvander@233: type->name_ = name; dvander@195: type->token_ = token; dvander@195: return type; dvander@195: } dvander@195: dvander@195: // :TODO: this leaks an interior pointer. dvander@195: const char * dvander@195: ke::GetTypeName(Type *type) dvander@195: { dvander@195: if (type->isArray()) dvander@195: return "array"; dvander@195: if (type->isFunction()) dvander@195: return "function"; dvander@195: if (type->isVoid()) dvander@195: return "void"; dvander@233: if (type->isEnum()) dvander@233: return EnumType::cast(type)->name()->chars(); dvander@233: if (type->isStruct()) dvander@233: return StructType::cast(type)->name()->chars(); dvander@195: if (type->isReference()) dvander@222: type = ReferenceType::cast(type)->contained(); dvander@195: switch (type->primitive()) { dvander@195: case PrimitiveType_Bool: dvander@195: return "bool"; dvander@195: case PrimitiveType_Char: dvander@195: return "String"; dvander@195: case PrimitiveType_Int32: dvander@195: return "int"; dvander@195: case PrimitiveType_Float: dvander@195: return "Float"; dvander@195: default: dvander@195: return ""; dvander@195: } dvander@195: }