diff -r c4b1341297e5 -r ba85a47ee414 src/Types.cpp --- a/src/Types.cpp Mon Jun 10 00:46:29 2013 +0100 +++ b/src/Types.cpp Mon Jun 10 01:04:43 2013 +0100 @@ -1,333 +1,333 @@ -/* vim: set ts=4 sw=4 tw=99 et: - * - * Copyright (C) 2012 David Anderson - * - * This file is part of SourcePawn. - * - * SourcePawn is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) - * any later version. - * - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * SourcePawn. If not, see http://www.gnu.org/licenses/. - */ -#include -#include "Types.h" -#include "Zone.h" -#include "Strings.h" -#include "Array.h" -#include "Structures.h" -#include "Heap-inl.h" - -using namespace ke; - -void -Type::init(Kind kind, Type *root) -{ - this->kind_ = kind; - this->root_ = root ? root : this; -} - -Type * -Type::NewVoid(Zone *zone) -{ - Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); - if (!type) - return NULL; - - type->init(VOID); - return type; -} - -Type * -Type::NewImportable(Zone *zone) -{ - Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); - if (!type) - return NULL; - - type->init(IMPORTABLE); - return type; -} - -Type * -Type::NewString(Zone *zone) -{ - Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); - if (!type) - return NULL; - - type->init(STRING); - return type; -} - -Type * -Type::NewUnchecked(Zone *zone) -{ - Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); - if (!type) - return NULL; - - type->init(UNCHECKED); - return type; -} - -Type * -Type::NewType(Zone *zone) -{ - Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); - if (!type) - return NULL; - - type->init(TYPE); - return type; -} - -Type * -Type::NewPrimitive(Zone *zone, PrimitiveType prim) -{ - Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); - if (!type) - return NULL; - - type->init(PRIMITIVE); - type->primitive_ = prim; - return type; -} - -Type * -Type::NewQualified(Zone *zone, TypeQualifiers qual, Handle root) -{ - Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); - if (!type) - return NULL; - - type->init(QUALTYPE, root); - type->quals_ = qual; - return type; -} - -ArrayType * -ArrayType::New(Zone *zone, Handle contained, int elements) -{ - if (contained->isArray() && - ArrayType::cast(contained)->levels() == MAX_ARRAY_DEPTH) - { - zone->reportError(Message_MaximumArrayDepth); - return NULL; - } - - Local type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old)); - if (!type) - return NULL; - - type->init(ARRAY); - type->contained_ = contained; - type->elements_ = elements; - if (!contained->isArray()) - type->levels_ = 1; - else - type->levels_ = ArrayType::cast(contained)->levels() + 1; - - type->newMap_ = ArrayMap::New(zone, type); - if (!type->newMap_) - return NULL; - - return type; -} - -ArrayType * -ArrayType::NewExternal(Zone *zone, Handle contained) -{ - Local type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old)); - if (!type) - return NULL; - - assert(contained->isPrimitive()); - - type->init(EXTERNAL_ARRAY); - type->contained_ = contained; - type->elements_ = DYNAMIC_ARRAY_SIZE; - type->levels_ = 1; - return type; -} - -ReferenceType * -ReferenceType::New(Zone *zone, Handle contained) -{ - Local type(zone, (ReferenceType *)zone->allocate(MapKind_ReferenceType, sizeof(ReferenceType), Heap::Tenure_Old)); - if (!type) - return NULL; - - type->init(REFERENCE); - type->contained_ = contained; - return type; -} - -EnumType * -EnumType::New(Zone *zone, Handle name) -{ - Local type(zone, (EnumType *)zone->allocate(MapKind_EnumType, sizeof(EnumType), Heap::Tenure_Old)); - if (!type) - return NULL; - - type->init(ENUM); - type->name_ = name; - type->fields_ = NULL; - return type; -} - -StructType * -StructType::New(Zone *zone, Handle name, Handle fields) -{ - Local type(zone, (StructType *)zone->allocate(MapKind_StructType, sizeof(StructType), Heap::Tenure_Old)); - if (!type) - return NULL; - - type->init(STRUCT); - type->newMap_ = NULL; - type->fields_ = fields; - type->name_ = name; - - // Fill in field offsets. - StructureBufferBuilder builder; - Local fieldType(zone); - for (size_t i = 0; i < fields->length(); i++) { - Descriptor *desc = Descriptor::cast(fields->at(i)); - fieldType = desc->type(); - - unsigned offset; - if (!builder.add(fieldType, &offset)) - return NULL; - desc->setOffset(offset); - } - - Local map(zone, StructMap::New(zone, builder, type)); - if (!map) - return NULL; - - type->newMap_ = map; - - return type; -} - -Descriptor * -StructType::lookupField(String *name, unsigned *index) -{ - // :TODO: assert no GC - for (unsigned i = 0; i < fields_->length(); i++) { - Descriptor *desc = Descriptor::cast(fields_->at(i)); - if (desc->name() == name) { - if (index) - *index = i; - return desc; - } - } - - return NULL; -} - -FunctionType * -FunctionType::New(Zone *zone, Handle name, TokenKind token) -{ - Local type(zone, (FunctionType *)zone->allocate(MapKind_FunctionType, sizeof(FunctionType), Heap::Tenure_Old)); - if (!type) - return NULL; - - type->init(FUNCTION); - type->parameters_ = NULL; - type->defaults_ = NULL; - type->returnType_ = NULL; - type->name_ = name; - type->token_ = token; - return type; -} - -static size_t -FormatVA(char *buffer, size_t maxlen, const char *text, va_list ap) -{ - size_t len = vsnprintf(buffer, maxlen, text, ap); - if (len >= maxlen) { - buffer[maxlen - 1] = '\0'; - return maxlen - 1; - } - return len; -} - -static size_t -Format(char *buffer, size_t maxlen, const char *text, ...) -{ - va_list ap; - va_start(ap, text); - size_t len = FormatVA(buffer, maxlen, text, ap); - va_end(ap); - return len; -} - -static size_t -FormatTypeName(Type *type, char *buffer, size_t maxlen) -{ - if (type->isArray()) { - ArrayType *atype = ArrayType::cast(type); - Type *innermost = atype->innermost(); - - size_t len = FormatTypeName(innermost, buffer, maxlen); - for (;;) { - if (atype->isFixedLength()) - len += Format(buffer + len, maxlen - len, "[%d]", atype->fixedLength()); - else - len += Format(buffer + len, maxlen - len, "[]"); - if (!atype->contained()->isArray()) - break; - atype = ArrayType::cast(atype->contained()); - } - return len; - } - if (type->hasTypeQualifiers()) { - size_t len = 0; - if (type->quals() & TypeQual_Const) - len += Format(buffer, maxlen, "const "); - return len + FormatTypeName(type->unqualified(), buffer + len, maxlen - len); - } - if (type->isFunction()) - return Format(buffer, maxlen, "function"); - if (type->isVoid()) - return Format(buffer, maxlen, "void"); - if (type->isUnchecked()) - return Format(buffer, maxlen, "unchecked"); - if (type->isImportable()) - return Format(buffer, maxlen, "import"); - if (type->isEnum()) - return Format(buffer, maxlen, "%s", EnumType::cast(type)->name()->chars()); - if (type->isStruct()) - return Format(buffer, maxlen, "%s", StructType::cast(type)->name()->chars()); - if (type->isReference()) { - ReferenceType *ref = ReferenceType::cast(type); - size_t len = Format(buffer, maxlen, "&"); - return len + FormatTypeName(ref->contained(), buffer + len, maxlen - len); - } - switch (type->primitive()) { - case PrimitiveType_Bool: - return Format(buffer, maxlen, "bool"); - case PrimitiveType_Char: - return Format(buffer, maxlen, "char"); - case PrimitiveType_Int32: - return Format(buffer, maxlen, "int"); - case PrimitiveType_Float: - return Format(buffer, maxlen, "float"); - default: - return Format(buffer, maxlen, ""); - } -} - -const char * -ke::GetTypeName(Type *type, char *buffer, size_t maxlen) -{ - FormatTypeName(type, buffer, maxlen); - return buffer; -} +/* vim: set ts=4 sw=4 tw=99 et: + * + * Copyright (C) 2012 David Anderson + * + * This file is part of SourcePawn. + * + * SourcePawn is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * SourcePawn. If not, see http://www.gnu.org/licenses/. + */ +#include +#include "Types.h" +#include "Zone.h" +#include "Strings.h" +#include "Array.h" +#include "Structures.h" +#include "Heap-inl.h" + +using namespace ke; + +void +Type::init(Kind kind, Type *root) +{ + this->kind_ = kind; + this->root_ = root ? root : this; +} + +Type * +Type::NewVoid(Zone *zone) +{ + Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); + if (!type) + return NULL; + + type->init(VOID); + return type; +} + +Type * +Type::NewImportable(Zone *zone) +{ + Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); + if (!type) + return NULL; + + type->init(IMPORTABLE); + return type; +} + +Type * +Type::NewString(Zone *zone) +{ + Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); + if (!type) + return NULL; + + type->init(STRING); + return type; +} + +Type * +Type::NewUnchecked(Zone *zone) +{ + Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); + if (!type) + return NULL; + + type->init(UNCHECKED); + return type; +} + +Type * +Type::NewType(Zone *zone) +{ + Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); + if (!type) + return NULL; + + type->init(TYPE); + return type; +} + +Type * +Type::NewPrimitive(Zone *zone, PrimitiveType prim) +{ + Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); + if (!type) + return NULL; + + type->init(PRIMITIVE); + type->primitive_ = prim; + return type; +} + +Type * +Type::NewQualified(Zone *zone, TypeQualifiers qual, Handle root) +{ + Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); + if (!type) + return NULL; + + type->init(QUALTYPE, root); + type->quals_ = qual; + return type; +} + +ArrayType * +ArrayType::New(Zone *zone, Handle contained, int elements) +{ + if (contained->isArray() && + ArrayType::cast(contained)->levels() == MAX_ARRAY_DEPTH) + { + zone->reportError(Message_MaximumArrayDepth); + return NULL; + } + + Local type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old)); + if (!type) + return NULL; + + type->init(ARRAY); + type->contained_ = contained; + type->elements_ = elements; + if (!contained->isArray()) + type->levels_ = 1; + else + type->levels_ = ArrayType::cast(contained)->levels() + 1; + + type->newMap_ = ArrayMap::New(zone, type); + if (!type->newMap_) + return NULL; + + return type; +} + +ArrayType * +ArrayType::NewExternal(Zone *zone, Handle contained) +{ + Local type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old)); + if (!type) + return NULL; + + assert(contained->isPrimitive()); + + type->init(EXTERNAL_ARRAY); + type->contained_ = contained; + type->elements_ = DYNAMIC_ARRAY_SIZE; + type->levels_ = 1; + return type; +} + +ReferenceType * +ReferenceType::New(Zone *zone, Handle contained) +{ + Local type(zone, (ReferenceType *)zone->allocate(MapKind_ReferenceType, sizeof(ReferenceType), Heap::Tenure_Old)); + if (!type) + return NULL; + + type->init(REFERENCE); + type->contained_ = contained; + return type; +} + +EnumType * +EnumType::New(Zone *zone, Handle name) +{ + Local type(zone, (EnumType *)zone->allocate(MapKind_EnumType, sizeof(EnumType), Heap::Tenure_Old)); + if (!type) + return NULL; + + type->init(ENUM); + type->name_ = name; + type->fields_ = NULL; + return type; +} + +StructType * +StructType::New(Zone *zone, Handle name, Handle fields) +{ + Local type(zone, (StructType *)zone->allocate(MapKind_StructType, sizeof(StructType), Heap::Tenure_Old)); + if (!type) + return NULL; + + type->init(STRUCT); + type->newMap_ = NULL; + type->fields_ = fields; + type->name_ = name; + + // Fill in field offsets. + StructureBufferBuilder builder; + Local fieldType(zone); + for (size_t i = 0; i < fields->length(); i++) { + Descriptor *desc = Descriptor::cast(fields->at(i)); + fieldType = desc->type(); + + unsigned offset; + if (!builder.add(fieldType, &offset)) + return NULL; + desc->setOffset(offset); + } + + Local map(zone, StructMap::New(zone, builder, type)); + if (!map) + return NULL; + + type->newMap_ = map; + + return type; +} + +Descriptor * +StructType::lookupField(String *name, unsigned *index) +{ + // :TODO: assert no GC + for (unsigned i = 0; i < fields_->length(); i++) { + Descriptor *desc = Descriptor::cast(fields_->at(i)); + if (desc->name() == name) { + if (index) + *index = i; + return desc; + } + } + + return NULL; +} + +FunctionType * +FunctionType::New(Zone *zone, Handle name, TokenKind token) +{ + Local type(zone, (FunctionType *)zone->allocate(MapKind_FunctionType, sizeof(FunctionType), Heap::Tenure_Old)); + if (!type) + return NULL; + + type->init(FUNCTION); + type->parameters_ = NULL; + type->defaults_ = NULL; + type->returnType_ = NULL; + type->name_ = name; + type->token_ = token; + return type; +} + +static size_t +FormatVA(char *buffer, size_t maxlen, const char *text, va_list ap) +{ + size_t len = vsnprintf(buffer, maxlen, text, ap); + if (len >= maxlen) { + buffer[maxlen - 1] = '\0'; + return maxlen - 1; + } + return len; +} + +static size_t +Format(char *buffer, size_t maxlen, const char *text, ...) +{ + va_list ap; + va_start(ap, text); + size_t len = FormatVA(buffer, maxlen, text, ap); + va_end(ap); + return len; +} + +static size_t +FormatTypeName(Type *type, char *buffer, size_t maxlen) +{ + if (type->isArray()) { + ArrayType *atype = ArrayType::cast(type); + Type *innermost = atype->innermost(); + + size_t len = FormatTypeName(innermost, buffer, maxlen); + for (;;) { + if (atype->isFixedLength()) + len += Format(buffer + len, maxlen - len, "[%d]", atype->fixedLength()); + else + len += Format(buffer + len, maxlen - len, "[]"); + if (!atype->contained()->isArray()) + break; + atype = ArrayType::cast(atype->contained()); + } + return len; + } + if (type->hasTypeQualifiers()) { + size_t len = 0; + if (type->quals() & TypeQual_Const) + len += Format(buffer, maxlen, "const "); + return len + FormatTypeName(type->unqualified(), buffer + len, maxlen - len); + } + if (type->isFunction()) + return Format(buffer, maxlen, "function"); + if (type->isVoid()) + return Format(buffer, maxlen, "void"); + if (type->isUnchecked()) + return Format(buffer, maxlen, "unchecked"); + if (type->isImportable()) + return Format(buffer, maxlen, "import"); + if (type->isEnum()) + return Format(buffer, maxlen, "%s", EnumType::cast(type)->name()->chars()); + if (type->isStruct()) + return Format(buffer, maxlen, "%s", StructType::cast(type)->name()->chars()); + if (type->isReference()) { + ReferenceType *ref = ReferenceType::cast(type); + size_t len = Format(buffer, maxlen, "&"); + return len + FormatTypeName(ref->contained(), buffer + len, maxlen - len); + } + switch (type->primitive()) { + case PrimitiveType_Bool: + return Format(buffer, maxlen, "bool"); + case PrimitiveType_Char: + return Format(buffer, maxlen, "char"); + case PrimitiveType_Int32: + return Format(buffer, maxlen, "int"); + case PrimitiveType_Float: + return Format(buffer, maxlen, "float"); + default: + return Format(buffer, maxlen, ""); + } +} + +const char * +ke::GetTypeName(Type *type, char *buffer, size_t maxlen) +{ + FormatTypeName(type, buffer, maxlen); + return buffer; +}