1.1 --- a/src/Types.cpp Mon Jun 10 00:46:29 2013 +0100
1.2 +++ b/src/Types.cpp Mon Jun 10 01:04:43 2013 +0100
1.3 @@ -1,333 +1,333 @@
1.4 -/* vim: set ts=4 sw=4 tw=99 et:
1.5 - *
1.6 - * Copyright (C) 2012 David Anderson
1.7 - *
1.8 - * This file is part of SourcePawn.
1.9 - *
1.10 - * SourcePawn is free software: you can redistribute it and/or modify it under
1.11 - * the terms of the GNU General Public License as published by the Free
1.12 - * Software Foundation, either version 3 of the License, or (at your option)
1.13 - * any later version.
1.14 - *
1.15 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
1.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.18 - *
1.19 - * You should have received a copy of the GNU General Public License along with
1.20 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
1.21 - */
1.22 -#include <string.h>
1.23 -#include "Types.h"
1.24 -#include "Zone.h"
1.25 -#include "Strings.h"
1.26 -#include "Array.h"
1.27 -#include "Structures.h"
1.28 -#include "Heap-inl.h"
1.29 -
1.30 -using namespace ke;
1.31 -
1.32 -void
1.33 -Type::init(Kind kind, Type *root)
1.34 -{
1.35 - this->kind_ = kind;
1.36 - this->root_ = root ? root : this;
1.37 -}
1.38 -
1.39 -Type *
1.40 -Type::NewVoid(Zone *zone)
1.41 -{
1.42 - Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
1.43 - if (!type)
1.44 - return NULL;
1.45 -
1.46 - type->init(VOID);
1.47 - return type;
1.48 -}
1.49 -
1.50 -Type *
1.51 -Type::NewImportable(Zone *zone)
1.52 -{
1.53 - Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
1.54 - if (!type)
1.55 - return NULL;
1.56 -
1.57 - type->init(IMPORTABLE);
1.58 - return type;
1.59 -}
1.60 -
1.61 -Type *
1.62 -Type::NewString(Zone *zone)
1.63 -{
1.64 - Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
1.65 - if (!type)
1.66 - return NULL;
1.67 -
1.68 - type->init(STRING);
1.69 - return type;
1.70 -}
1.71 -
1.72 -Type *
1.73 -Type::NewUnchecked(Zone *zone)
1.74 -{
1.75 - Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
1.76 - if (!type)
1.77 - return NULL;
1.78 -
1.79 - type->init(UNCHECKED);
1.80 - return type;
1.81 -}
1.82 -
1.83 -Type *
1.84 -Type::NewType(Zone *zone)
1.85 -{
1.86 - Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
1.87 - if (!type)
1.88 - return NULL;
1.89 -
1.90 - type->init(TYPE);
1.91 - return type;
1.92 -}
1.93 -
1.94 -Type *
1.95 -Type::NewPrimitive(Zone *zone, PrimitiveType prim)
1.96 -{
1.97 - Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
1.98 - if (!type)
1.99 - return NULL;
1.100 -
1.101 - type->init(PRIMITIVE);
1.102 - type->primitive_ = prim;
1.103 - return type;
1.104 -}
1.105 -
1.106 -Type *
1.107 -Type::NewQualified(Zone *zone, TypeQualifiers qual, Handle<Type> root)
1.108 -{
1.109 - Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
1.110 - if (!type)
1.111 - return NULL;
1.112 -
1.113 - type->init(QUALTYPE, root);
1.114 - type->quals_ = qual;
1.115 - return type;
1.116 -}
1.117 -
1.118 -ArrayType *
1.119 -ArrayType::New(Zone *zone, Handle<Type> contained, int elements)
1.120 -{
1.121 - if (contained->isArray() &&
1.122 - ArrayType::cast(contained)->levels() == MAX_ARRAY_DEPTH)
1.123 - {
1.124 - zone->reportError(Message_MaximumArrayDepth);
1.125 - return NULL;
1.126 - }
1.127 -
1.128 - Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
1.129 - if (!type)
1.130 - return NULL;
1.131 -
1.132 - type->init(ARRAY);
1.133 - type->contained_ = contained;
1.134 - type->elements_ = elements;
1.135 - if (!contained->isArray())
1.136 - type->levels_ = 1;
1.137 - else
1.138 - type->levels_ = ArrayType::cast(contained)->levels() + 1;
1.139 -
1.140 - type->newMap_ = ArrayMap::New(zone, type);
1.141 - if (!type->newMap_)
1.142 - return NULL;
1.143 -
1.144 - return type;
1.145 -}
1.146 -
1.147 -ArrayType *
1.148 -ArrayType::NewExternal(Zone *zone, Handle<Type> contained)
1.149 -{
1.150 - Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
1.151 - if (!type)
1.152 - return NULL;
1.153 -
1.154 - assert(contained->isPrimitive());
1.155 -
1.156 - type->init(EXTERNAL_ARRAY);
1.157 - type->contained_ = contained;
1.158 - type->elements_ = DYNAMIC_ARRAY_SIZE;
1.159 - type->levels_ = 1;
1.160 - return type;
1.161 -}
1.162 -
1.163 -ReferenceType *
1.164 -ReferenceType::New(Zone *zone, Handle<Type> contained)
1.165 -{
1.166 - Local<ReferenceType> type(zone, (ReferenceType *)zone->allocate(MapKind_ReferenceType, sizeof(ReferenceType), Heap::Tenure_Old));
1.167 - if (!type)
1.168 - return NULL;
1.169 -
1.170 - type->init(REFERENCE);
1.171 - type->contained_ = contained;
1.172 - return type;
1.173 -}
1.174 -
1.175 -EnumType *
1.176 -EnumType::New(Zone *zone, Handle<String> name)
1.177 -{
1.178 - Local<EnumType> type(zone, (EnumType *)zone->allocate(MapKind_EnumType, sizeof(EnumType), Heap::Tenure_Old));
1.179 - if (!type)
1.180 - return NULL;
1.181 -
1.182 - type->init(ENUM);
1.183 - type->name_ = name;
1.184 - type->fields_ = NULL;
1.185 - return type;
1.186 -}
1.187 -
1.188 -StructType *
1.189 -StructType::New(Zone *zone, Handle<String> name, Handle<FixedArray> fields)
1.190 -{
1.191 - Local<StructType> type(zone, (StructType *)zone->allocate(MapKind_StructType, sizeof(StructType), Heap::Tenure_Old));
1.192 - if (!type)
1.193 - return NULL;
1.194 -
1.195 - type->init(STRUCT);
1.196 - type->newMap_ = NULL;
1.197 - type->fields_ = fields;
1.198 - type->name_ = name;
1.199 -
1.200 - // Fill in field offsets.
1.201 - StructureBufferBuilder builder;
1.202 - Local<Type> fieldType(zone);
1.203 - for (size_t i = 0; i < fields->length(); i++) {
1.204 - Descriptor *desc = Descriptor::cast(fields->at(i));
1.205 - fieldType = desc->type();
1.206 -
1.207 - unsigned offset;
1.208 - if (!builder.add(fieldType, &offset))
1.209 - return NULL;
1.210 - desc->setOffset(offset);
1.211 - }
1.212 -
1.213 - Local<StructMap> map(zone, StructMap::New(zone, builder, type));
1.214 - if (!map)
1.215 - return NULL;
1.216 -
1.217 - type->newMap_ = map;
1.218 -
1.219 - return type;
1.220 -}
1.221 -
1.222 -Descriptor *
1.223 -StructType::lookupField(String *name, unsigned *index)
1.224 -{
1.225 - // :TODO: assert no GC
1.226 - for (unsigned i = 0; i < fields_->length(); i++) {
1.227 - Descriptor *desc = Descriptor::cast(fields_->at(i));
1.228 - if (desc->name() == name) {
1.229 - if (index)
1.230 - *index = i;
1.231 - return desc;
1.232 - }
1.233 - }
1.234 -
1.235 - return NULL;
1.236 -}
1.237 -
1.238 -FunctionType *
1.239 -FunctionType::New(Zone *zone, Handle<String> name, TokenKind token)
1.240 -{
1.241 - Local<FunctionType> type(zone, (FunctionType *)zone->allocate(MapKind_FunctionType, sizeof(FunctionType), Heap::Tenure_Old));
1.242 - if (!type)
1.243 - return NULL;
1.244 -
1.245 - type->init(FUNCTION);
1.246 - type->parameters_ = NULL;
1.247 - type->defaults_ = NULL;
1.248 - type->returnType_ = NULL;
1.249 - type->name_ = name;
1.250 - type->token_ = token;
1.251 - return type;
1.252 -}
1.253 -
1.254 -static size_t
1.255 -FormatVA(char *buffer, size_t maxlen, const char *text, va_list ap)
1.256 -{
1.257 - size_t len = vsnprintf(buffer, maxlen, text, ap);
1.258 - if (len >= maxlen) {
1.259 - buffer[maxlen - 1] = '\0';
1.260 - return maxlen - 1;
1.261 - }
1.262 - return len;
1.263 -}
1.264 -
1.265 -static size_t
1.266 -Format(char *buffer, size_t maxlen, const char *text, ...)
1.267 -{
1.268 - va_list ap;
1.269 - va_start(ap, text);
1.270 - size_t len = FormatVA(buffer, maxlen, text, ap);
1.271 - va_end(ap);
1.272 - return len;
1.273 -}
1.274 -
1.275 -static size_t
1.276 -FormatTypeName(Type *type, char *buffer, size_t maxlen)
1.277 -{
1.278 - if (type->isArray()) {
1.279 - ArrayType *atype = ArrayType::cast(type);
1.280 - Type *innermost = atype->innermost();
1.281 -
1.282 - size_t len = FormatTypeName(innermost, buffer, maxlen);
1.283 - for (;;) {
1.284 - if (atype->isFixedLength())
1.285 - len += Format(buffer + len, maxlen - len, "[%d]", atype->fixedLength());
1.286 - else
1.287 - len += Format(buffer + len, maxlen - len, "[]");
1.288 - if (!atype->contained()->isArray())
1.289 - break;
1.290 - atype = ArrayType::cast(atype->contained());
1.291 - }
1.292 - return len;
1.293 - }
1.294 - if (type->hasTypeQualifiers()) {
1.295 - size_t len = 0;
1.296 - if (type->quals() & TypeQual_Const)
1.297 - len += Format(buffer, maxlen, "const ");
1.298 - return len + FormatTypeName(type->unqualified(), buffer + len, maxlen - len);
1.299 - }
1.300 - if (type->isFunction())
1.301 - return Format(buffer, maxlen, "function");
1.302 - if (type->isVoid())
1.303 - return Format(buffer, maxlen, "void");
1.304 - if (type->isUnchecked())
1.305 - return Format(buffer, maxlen, "unchecked");
1.306 - if (type->isImportable())
1.307 - return Format(buffer, maxlen, "import");
1.308 - if (type->isEnum())
1.309 - return Format(buffer, maxlen, "%s", EnumType::cast(type)->name()->chars());
1.310 - if (type->isStruct())
1.311 - return Format(buffer, maxlen, "%s", StructType::cast(type)->name()->chars());
1.312 - if (type->isReference()) {
1.313 - ReferenceType *ref = ReferenceType::cast(type);
1.314 - size_t len = Format(buffer, maxlen, "&");
1.315 - return len + FormatTypeName(ref->contained(), buffer + len, maxlen - len);
1.316 - }
1.317 - switch (type->primitive()) {
1.318 - case PrimitiveType_Bool:
1.319 - return Format(buffer, maxlen, "bool");
1.320 - case PrimitiveType_Char:
1.321 - return Format(buffer, maxlen, "char");
1.322 - case PrimitiveType_Int32:
1.323 - return Format(buffer, maxlen, "int");
1.324 - case PrimitiveType_Float:
1.325 - return Format(buffer, maxlen, "float");
1.326 - default:
1.327 - return Format(buffer, maxlen, "<UNKNOWN>");
1.328 - }
1.329 -}
1.330 -
1.331 -const char *
1.332 -ke::GetTypeName(Type *type, char *buffer, size_t maxlen)
1.333 -{
1.334 - FormatTypeName(type, buffer, maxlen);
1.335 - return buffer;
1.336 -}
1.337 +/* vim: set ts=4 sw=4 tw=99 et:
1.338 + *
1.339 + * Copyright (C) 2012 David Anderson
1.340 + *
1.341 + * This file is part of SourcePawn.
1.342 + *
1.343 + * SourcePawn is free software: you can redistribute it and/or modify it under
1.344 + * the terms of the GNU General Public License as published by the Free
1.345 + * Software Foundation, either version 3 of the License, or (at your option)
1.346 + * any later version.
1.347 + *
1.348 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
1.349 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.350 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.351 + *
1.352 + * You should have received a copy of the GNU General Public License along with
1.353 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
1.354 + */
1.355 +#include <string.h>
1.356 +#include "Types.h"
1.357 +#include "Zone.h"
1.358 +#include "Strings.h"
1.359 +#include "Array.h"
1.360 +#include "Structures.h"
1.361 +#include "Heap-inl.h"
1.362 +
1.363 +using namespace ke;
1.364 +
1.365 +void
1.366 +Type::init(Kind kind, Type *root)
1.367 +{
1.368 + this->kind_ = kind;
1.369 + this->root_ = root ? root : this;
1.370 +}
1.371 +
1.372 +Type *
1.373 +Type::NewVoid(Zone *zone)
1.374 +{
1.375 + Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
1.376 + if (!type)
1.377 + return NULL;
1.378 +
1.379 + type->init(VOID);
1.380 + return type;
1.381 +}
1.382 +
1.383 +Type *
1.384 +Type::NewImportable(Zone *zone)
1.385 +{
1.386 + Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
1.387 + if (!type)
1.388 + return NULL;
1.389 +
1.390 + type->init(IMPORTABLE);
1.391 + return type;
1.392 +}
1.393 +
1.394 +Type *
1.395 +Type::NewString(Zone *zone)
1.396 +{
1.397 + Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
1.398 + if (!type)
1.399 + return NULL;
1.400 +
1.401 + type->init(STRING);
1.402 + return type;
1.403 +}
1.404 +
1.405 +Type *
1.406 +Type::NewUnchecked(Zone *zone)
1.407 +{
1.408 + Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
1.409 + if (!type)
1.410 + return NULL;
1.411 +
1.412 + type->init(UNCHECKED);
1.413 + return type;
1.414 +}
1.415 +
1.416 +Type *
1.417 +Type::NewType(Zone *zone)
1.418 +{
1.419 + Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
1.420 + if (!type)
1.421 + return NULL;
1.422 +
1.423 + type->init(TYPE);
1.424 + return type;
1.425 +}
1.426 +
1.427 +Type *
1.428 +Type::NewPrimitive(Zone *zone, PrimitiveType prim)
1.429 +{
1.430 + Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
1.431 + if (!type)
1.432 + return NULL;
1.433 +
1.434 + type->init(PRIMITIVE);
1.435 + type->primitive_ = prim;
1.436 + return type;
1.437 +}
1.438 +
1.439 +Type *
1.440 +Type::NewQualified(Zone *zone, TypeQualifiers qual, Handle<Type> root)
1.441 +{
1.442 + Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
1.443 + if (!type)
1.444 + return NULL;
1.445 +
1.446 + type->init(QUALTYPE, root);
1.447 + type->quals_ = qual;
1.448 + return type;
1.449 +}
1.450 +
1.451 +ArrayType *
1.452 +ArrayType::New(Zone *zone, Handle<Type> contained, int elements)
1.453 +{
1.454 + if (contained->isArray() &&
1.455 + ArrayType::cast(contained)->levels() == MAX_ARRAY_DEPTH)
1.456 + {
1.457 + zone->reportError(Message_MaximumArrayDepth);
1.458 + return NULL;
1.459 + }
1.460 +
1.461 + Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
1.462 + if (!type)
1.463 + return NULL;
1.464 +
1.465 + type->init(ARRAY);
1.466 + type->contained_ = contained;
1.467 + type->elements_ = elements;
1.468 + if (!contained->isArray())
1.469 + type->levels_ = 1;
1.470 + else
1.471 + type->levels_ = ArrayType::cast(contained)->levels() + 1;
1.472 +
1.473 + type->newMap_ = ArrayMap::New(zone, type);
1.474 + if (!type->newMap_)
1.475 + return NULL;
1.476 +
1.477 + return type;
1.478 +}
1.479 +
1.480 +ArrayType *
1.481 +ArrayType::NewExternal(Zone *zone, Handle<Type> contained)
1.482 +{
1.483 + Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
1.484 + if (!type)
1.485 + return NULL;
1.486 +
1.487 + assert(contained->isPrimitive());
1.488 +
1.489 + type->init(EXTERNAL_ARRAY);
1.490 + type->contained_ = contained;
1.491 + type->elements_ = DYNAMIC_ARRAY_SIZE;
1.492 + type->levels_ = 1;
1.493 + return type;
1.494 +}
1.495 +
1.496 +ReferenceType *
1.497 +ReferenceType::New(Zone *zone, Handle<Type> contained)
1.498 +{
1.499 + Local<ReferenceType> type(zone, (ReferenceType *)zone->allocate(MapKind_ReferenceType, sizeof(ReferenceType), Heap::Tenure_Old));
1.500 + if (!type)
1.501 + return NULL;
1.502 +
1.503 + type->init(REFERENCE);
1.504 + type->contained_ = contained;
1.505 + return type;
1.506 +}
1.507 +
1.508 +EnumType *
1.509 +EnumType::New(Zone *zone, Handle<String> name)
1.510 +{
1.511 + Local<EnumType> type(zone, (EnumType *)zone->allocate(MapKind_EnumType, sizeof(EnumType), Heap::Tenure_Old));
1.512 + if (!type)
1.513 + return NULL;
1.514 +
1.515 + type->init(ENUM);
1.516 + type->name_ = name;
1.517 + type->fields_ = NULL;
1.518 + return type;
1.519 +}
1.520 +
1.521 +StructType *
1.522 +StructType::New(Zone *zone, Handle<String> name, Handle<FixedArray> fields)
1.523 +{
1.524 + Local<StructType> type(zone, (StructType *)zone->allocate(MapKind_StructType, sizeof(StructType), Heap::Tenure_Old));
1.525 + if (!type)
1.526 + return NULL;
1.527 +
1.528 + type->init(STRUCT);
1.529 + type->newMap_ = NULL;
1.530 + type->fields_ = fields;
1.531 + type->name_ = name;
1.532 +
1.533 + // Fill in field offsets.
1.534 + StructureBufferBuilder builder;
1.535 + Local<Type> fieldType(zone);
1.536 + for (size_t i = 0; i < fields->length(); i++) {
1.537 + Descriptor *desc = Descriptor::cast(fields->at(i));
1.538 + fieldType = desc->type();
1.539 +
1.540 + unsigned offset;
1.541 + if (!builder.add(fieldType, &offset))
1.542 + return NULL;
1.543 + desc->setOffset(offset);
1.544 + }
1.545 +
1.546 + Local<StructMap> map(zone, StructMap::New(zone, builder, type));
1.547 + if (!map)
1.548 + return NULL;
1.549 +
1.550 + type->newMap_ = map;
1.551 +
1.552 + return type;
1.553 +}
1.554 +
1.555 +Descriptor *
1.556 +StructType::lookupField(String *name, unsigned *index)
1.557 +{
1.558 + // :TODO: assert no GC
1.559 + for (unsigned i = 0; i < fields_->length(); i++) {
1.560 + Descriptor *desc = Descriptor::cast(fields_->at(i));
1.561 + if (desc->name() == name) {
1.562 + if (index)
1.563 + *index = i;
1.564 + return desc;
1.565 + }
1.566 + }
1.567 +
1.568 + return NULL;
1.569 +}
1.570 +
1.571 +FunctionType *
1.572 +FunctionType::New(Zone *zone, Handle<String> name, TokenKind token)
1.573 +{
1.574 + Local<FunctionType> type(zone, (FunctionType *)zone->allocate(MapKind_FunctionType, sizeof(FunctionType), Heap::Tenure_Old));
1.575 + if (!type)
1.576 + return NULL;
1.577 +
1.578 + type->init(FUNCTION);
1.579 + type->parameters_ = NULL;
1.580 + type->defaults_ = NULL;
1.581 + type->returnType_ = NULL;
1.582 + type->name_ = name;
1.583 + type->token_ = token;
1.584 + return type;
1.585 +}
1.586 +
1.587 +static size_t
1.588 +FormatVA(char *buffer, size_t maxlen, const char *text, va_list ap)
1.589 +{
1.590 + size_t len = vsnprintf(buffer, maxlen, text, ap);
1.591 + if (len >= maxlen) {
1.592 + buffer[maxlen - 1] = '\0';
1.593 + return maxlen - 1;
1.594 + }
1.595 + return len;
1.596 +}
1.597 +
1.598 +static size_t
1.599 +Format(char *buffer, size_t maxlen, const char *text, ...)
1.600 +{
1.601 + va_list ap;
1.602 + va_start(ap, text);
1.603 + size_t len = FormatVA(buffer, maxlen, text, ap);
1.604 + va_end(ap);
1.605 + return len;
1.606 +}
1.607 +
1.608 +static size_t
1.609 +FormatTypeName(Type *type, char *buffer, size_t maxlen)
1.610 +{
1.611 + if (type->isArray()) {
1.612 + ArrayType *atype = ArrayType::cast(type);
1.613 + Type *innermost = atype->innermost();
1.614 +
1.615 + size_t len = FormatTypeName(innermost, buffer, maxlen);
1.616 + for (;;) {
1.617 + if (atype->isFixedLength())
1.618 + len += Format(buffer + len, maxlen - len, "[%d]", atype->fixedLength());
1.619 + else
1.620 + len += Format(buffer + len, maxlen - len, "[]");
1.621 + if (!atype->contained()->isArray())
1.622 + break;
1.623 + atype = ArrayType::cast(atype->contained());
1.624 + }
1.625 + return len;
1.626 + }
1.627 + if (type->hasTypeQualifiers()) {
1.628 + size_t len = 0;
1.629 + if (type->quals() & TypeQual_Const)
1.630 + len += Format(buffer, maxlen, "const ");
1.631 + return len + FormatTypeName(type->unqualified(), buffer + len, maxlen - len);
1.632 + }
1.633 + if (type->isFunction())
1.634 + return Format(buffer, maxlen, "function");
1.635 + if (type->isVoid())
1.636 + return Format(buffer, maxlen, "void");
1.637 + if (type->isUnchecked())
1.638 + return Format(buffer, maxlen, "unchecked");
1.639 + if (type->isImportable())
1.640 + return Format(buffer, maxlen, "import");
1.641 + if (type->isEnum())
1.642 + return Format(buffer, maxlen, "%s", EnumType::cast(type)->name()->chars());
1.643 + if (type->isStruct())
1.644 + return Format(buffer, maxlen, "%s", StructType::cast(type)->name()->chars());
1.645 + if (type->isReference()) {
1.646 + ReferenceType *ref = ReferenceType::cast(type);
1.647 + size_t len = Format(buffer, maxlen, "&");
1.648 + return len + FormatTypeName(ref->contained(), buffer + len, maxlen - len);
1.649 + }
1.650 + switch (type->primitive()) {
1.651 + case PrimitiveType_Bool:
1.652 + return Format(buffer, maxlen, "bool");
1.653 + case PrimitiveType_Char:
1.654 + return Format(buffer, maxlen, "char");
1.655 + case PrimitiveType_Int32:
1.656 + return Format(buffer, maxlen, "int");
1.657 + case PrimitiveType_Float:
1.658 + return Format(buffer, maxlen, "float");
1.659 + default:
1.660 + return Format(buffer, maxlen, "<UNKNOWN>");
1.661 + }
1.662 +}
1.663 +
1.664 +const char *
1.665 +ke::GetTypeName(Type *type, char *buffer, size_t maxlen)
1.666 +{
1.667 + FormatTypeName(type, buffer, maxlen);
1.668 + return buffer;
1.669 +}