Add support for mutually recursive imports.
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of SourcePawn.
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)
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.
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/.
24 #include "Structures.h"
30 Type::init(Kind kind, Type *root)
33 this->root_ = root ? root : this;
37 Type::NewVoid(Zone *zone)
39 Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
48 Type::NewImportable(Zone *zone)
50 Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
54 type->init(IMPORTABLE);
59 Type::NewString(Zone *zone)
61 Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
70 Type::NewUnchecked(Zone *zone)
72 Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
76 type->init(UNCHECKED);
81 Type::NewPrimitive(Zone *zone, PrimitiveType prim)
83 Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
87 type->init(PRIMITIVE);
88 type->primitive_ = prim;
93 Type::NewQualified(Zone *zone, TypeQualifiers qual, Handle<Type> root)
95 Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
99 type->init(QUALTYPE, root);
105 ArrayType::New(Zone *zone, Handle<Type> contained, int elements)
107 if (contained->isArray() &&
108 ArrayType::cast(contained)->levels() == MAX_ARRAY_DEPTH)
110 zone->reportError(Message_MaximumArrayDepth);
114 Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
119 type->contained_ = contained;
120 type->elements_ = elements;
121 if (!contained->isArray())
124 type->levels_ = ArrayType::cast(contained)->levels() + 1;
126 type->newMap_ = ArrayMap::New(zone, type);
134 ArrayType::NewExternal(Zone *zone, Handle<Type> contained)
136 Local<ArrayType> type(zone, (ArrayType *)zone->allocate(MapKind_ArrayType, sizeof(ArrayType), Heap::Tenure_Old));
140 assert(contained->isPrimitive());
142 type->init(EXTERNAL_ARRAY);
143 type->contained_ = contained;
144 type->elements_ = DYNAMIC_ARRAY_SIZE;
150 ReferenceType::New(Zone *zone, Handle<Type> contained)
152 Local<ReferenceType> type(zone, (ReferenceType *)zone->allocate(MapKind_ReferenceType, sizeof(ReferenceType), Heap::Tenure_Old));
156 type->init(REFERENCE);
157 type->contained_ = contained;
162 EnumType::New(Zone *zone, Handle<String> name)
164 Local<EnumType> type(zone, (EnumType *)zone->allocate(MapKind_EnumType, sizeof(EnumType), Heap::Tenure_Old));
174 StructType::New(Zone *zone, Handle<String> name, Handle<FixedArray> fields)
176 Local<StructType> type(zone, (StructType *)zone->allocate(MapKind_StructType, sizeof(StructType), Heap::Tenure_Old));
181 type->newMap_ = NULL;
182 type->fields_ = fields;
185 // Fill in field offsets.
186 StructureBufferBuilder builder;
187 Local<Type> fieldType(zone);
188 for (size_t i = 0; i < fields->length(); i++) {
189 Descriptor *desc = Descriptor::cast(fields->at(i));
190 fieldType = desc->type();
193 if (!builder.add(fieldType, &offset))
195 desc->setOffset(offset);
198 Local<StructMap> map(zone, StructMap::New(zone, builder, type));
208 StructType::lookupField(String *name, unsigned *index)
210 // :TODO: assert no GC
211 for (unsigned i = 0; i < fields_->length(); i++) {
212 Descriptor *desc = Descriptor::cast(fields_->at(i));
213 if (desc->name() == name) {
224 FunctionType::New(Zone *zone, Handle<String> name, TokenKind token)
226 Local<FunctionType> type(zone, (FunctionType *)zone->allocate(MapKind_FunctionType, sizeof(FunctionType), Heap::Tenure_Old));
230 type->init(FUNCTION);
231 type->parameters_ = NULL;
232 type->defaults_ = NULL;
233 type->returnType_ = NULL;
235 type->token_ = token;
240 FormatVA(char *buffer, size_t maxlen, const char *text, va_list ap)
242 size_t len = vsnprintf(buffer, maxlen, text, ap);
244 buffer[maxlen - 1] = '\0';
251 Format(char *buffer, size_t maxlen, const char *text, ...)
255 size_t len = FormatVA(buffer, maxlen, text, ap);
261 FormatTypeName(Type *type, char *buffer, size_t maxlen)
263 if (type->isArray()) {
264 ArrayType *atype = ArrayType::cast(type);
265 Type *innermost = atype->innermost();
267 size_t len = FormatTypeName(innermost, buffer, maxlen);
269 if (atype->isFixedLength())
270 len += Format(buffer + len, maxlen - len, "[%d]", atype->fixedLength());
272 len += Format(buffer + len, maxlen - len, "[]");
273 if (!atype->contained()->isArray())
275 atype = ArrayType::cast(atype->contained());
279 if (type->hasTypeQualifiers()) {
281 if (type->quals() & TypeQual_Const)
282 len += Format(buffer, maxlen, "const ");
283 return len + FormatTypeName(type->unqualified(), buffer + len, maxlen - len);
285 if (type->isFunction())
286 return Format(buffer, maxlen, "function");
288 return Format(buffer, maxlen, "void");
289 if (type->isUnchecked())
290 return Format(buffer, maxlen, "unchecked");
291 if (type->isImportable())
292 return Format(buffer, maxlen, "import");
294 return Format(buffer, maxlen, "%s", EnumType::cast(type)->name()->chars());
295 if (type->isStruct())
296 return Format(buffer, maxlen, "%s", StructType::cast(type)->name()->chars());
297 if (type->isReference()) {
298 ReferenceType *ref = ReferenceType::cast(type);
299 size_t len = Format(buffer, maxlen, "&");
300 return len + FormatTypeName(ref->contained(), buffer + len, maxlen - len);
302 switch (type->primitive()) {
303 case PrimitiveType_Bool:
304 return Format(buffer, maxlen, "bool");
305 case PrimitiveType_Char:
306 return Format(buffer, maxlen, "char");
307 case PrimitiveType_Int32:
308 return Format(buffer, maxlen, "int");
309 case PrimitiveType_Float:
310 return Format(buffer, maxlen, "float");
312 return Format(buffer, maxlen, "<UNKNOWN>");
317 ke::GetTypeName(Type *type, char *buffer, size_t maxlen)
319 FormatTypeName(type, buffer, maxlen);