Preparatory refactoring for const types.
Preparatory refactoring for const types.
1.1 --- a/src/ObjectVisitor.h Mon Dec 24 16:43:22 2012 -0800
1.2 +++ b/src/ObjectVisitor.h Tue Dec 25 16:32:06 2012 -0800
1.3 @@ -46,6 +46,7 @@
1.4 }
1.5
1.6 size_t iterateType(Object *obj) {
1.7 + visitField(obj, Type::offsetOfRoot());
1.8 return sizeof(Type);
1.9 }
1.10
2.1 --- a/src/QualType.h Mon Dec 24 16:43:22 2012 -0800
2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2.3 @@ -1,51 +0,0 @@
2.4 -/* vim: set ts=4 sw=4 tw=99 et:
2.5 - *
2.6 - * Copyright (C) 2012 David Anderson
2.7 - *
2.8 - * This file is part of SourcePawn.
2.9 - *
2.10 - * SourcePawn is free software: you can redistribute it and/or modify it under
2.11 - * the terms of the GNU General Public License as published by the Free
2.12 - * Software Foundation, either version 3 of the License, or (at your option)
2.13 - * any later version.
2.14 - *
2.15 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
2.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
2.18 - *
2.19 - * You should have received a copy of the GNU General Public License along with
2.20 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
2.21 - */
2.22 -#ifndef _include_sp2_qualtype_h_
2.23 -#define _include_sp2_qualtype_h_
2.24 -
2.25 -#include "Objects.h"
2.26 -
2.27 -namespace ke {
2.28 -
2.29 -class Type;
2.30 -
2.31 -enum TypeQualifiers
2.32 -{
2.33 - Qual_None = 0,
2.34 - Qual_Const = (1 << 0),
2.35 - Qual_Public = (1 << 1),
2.36 - Total_Qualifiers
2.37 -};
2.38 -
2.39 -// A QualType is a fully-qualified type in the SP2 type system.
2.40 -class QualType : public Object
2.41 -{
2.42 - public:
2.43 -
2.44 -
2.45 - private:
2.46 - union {
2.47 - Type *type_;
2.48 - uintptr_t flags_;
2.49 - };
2.50 -};
2.51 -
2.52 -}
2.53 -
2.54 -#endif // _include_sp2_qualtype_h_
3.1 --- a/src/Types.cpp Mon Dec 24 16:43:22 2012 -0800
3.2 +++ b/src/Types.cpp Tue Dec 25 16:32:06 2012 -0800
3.3 @@ -25,6 +25,13 @@
3.4
3.5 using namespace ke;
3.6
3.7 +void
3.8 +Type::init(Kind kind)
3.9 +{
3.10 + this->kind_ = kind;
3.11 + this->root_ = this;
3.12 +}
3.13 +
3.14 Type *
3.15 Type::NewVoid(Zone *zone)
3.16 {
3.17 @@ -32,7 +39,7 @@
3.18 if (!type)
3.19 return NULL;
3.20
3.21 - type->kind_ = VOID;
3.22 + type->init(VOID);
3.23 return type;
3.24 }
3.25
3.26 @@ -43,7 +50,7 @@
3.27 if (!type)
3.28 return NULL;
3.29
3.30 - type->kind_ = STRING;
3.31 + type->init(STRING);
3.32 return type;
3.33 }
3.34
3.35 @@ -54,7 +61,7 @@
3.36 if (!type)
3.37 return NULL;
3.38
3.39 - type->kind_ = UNCHECKED;
3.40 + type->init(UNCHECKED);
3.41 return type;
3.42 }
3.43
3.44 @@ -65,7 +72,7 @@
3.45 if (!type)
3.46 return NULL;
3.47
3.48 - type->kind_ = PRIMITIVE;
3.49 + type->init(PRIMITIVE);
3.50 type->primitive_ = prim;
3.51 return type;
3.52 }
3.53 @@ -84,7 +91,7 @@
3.54 if (!type)
3.55 return NULL;
3.56
3.57 - type->kind_ = ARRAY;
3.58 + type->init(ARRAY);
3.59 type->contained_ = contained;
3.60 type->elements_ = elements;
3.61 if (!contained->isArray())
3.62 @@ -103,7 +110,7 @@
3.63
3.64 assert(contained->isPrimitive());
3.65
3.66 - type->kind_ = EXTERNAL_ARRAY;
3.67 + type->init(EXTERNAL_ARRAY);
3.68 type->contained_ = contained;
3.69 type->elements_ = DYNAMIC_ARRAY_SIZE;
3.70 type->levels_ = 1;
3.71 @@ -117,8 +124,7 @@
3.72 if (!type)
3.73 return NULL;
3.74
3.75 - type->kind_ = REFERENCE;
3.76 - type->const_ = false;
3.77 + type->init(REFERENCE);
3.78 type->contained_ = contained;
3.79 return type;
3.80 }
3.81 @@ -130,7 +136,7 @@
3.82 if (!type)
3.83 return NULL;
3.84
3.85 - type->kind_ = ENUM;
3.86 + type->init(ENUM);
3.87 type->name_ = name;
3.88 return type;
3.89 }
3.90 @@ -142,7 +148,7 @@
3.91 if (!type)
3.92 return NULL;
3.93
3.94 - type->kind_ = STRUCT;
3.95 + type->init(STRUCT);
3.96 type->newMap_ = NULL;
3.97 type->fields_ = fields;
3.98 type->name_ = name;
3.99 @@ -191,7 +197,7 @@
3.100 if (!type)
3.101 return NULL;
3.102
3.103 - type->kind_ = FUNCTION;
3.104 + type->init(FUNCTION);
3.105 type->parameters_ = NULL;
3.106 type->defaults_ = NULL;
3.107 type->returnType_ = NULL;
4.1 --- a/src/Types.h Mon Dec 24 16:43:22 2012 -0800
4.2 +++ b/src/Types.h Tue Dec 25 16:32:06 2012 -0800
4.3 @@ -1,484 +1,535 @@
4.4 -/* vim: set ts=4 sw=4 tw=99 et:
4.5 - *
4.6 - * Copyright (C) 2012 David Anderson
4.7 - *
4.8 - * This file is part of JITCraft.
4.9 - *
4.10 - * JITCraft is free software: you can redistribute it and/or modify it under
4.11 - * the terms of the GNU General Public License as published by the Free
4.12 - * Software Foundation, either version 3 of the License, or (at your option)
4.13 - * any later version.
4.14 - *
4.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
4.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
4.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
4.18 - *
4.19 - * You should have received a copy of the GNU General Public License along with
4.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
4.21 - */
4.22 -#ifndef _include_jc_types_h_
4.23 -#define _include_jc_types_h_
4.24 -
4.25 -#include "Heap.h"
4.26 -#include "Barriers.h"
4.27 -#include "FixedArray.h"
4.28 -#include "compiler/Token.h"
4.29 -
4.30 -namespace ke {
4.31 -
4.32 -class String;
4.33 -class Descriptor;
4.34 -class StructMap;
4.35 -class ArrayMap;
4.36 -
4.37 -#define MAX_ARRAY_DEPTH 5
4.38 -
4.39 -enum PrimitiveType
4.40 -{
4.41 - // A boolean type semantically represents 0 or 1. As an optimization, its
4.42 - // internal storage type is the same as int32, and any non-zero value
4.43 - // compares positively to "true".
4.44 - PrimitiveType_Bool,
4.45 -
4.46 - // A character is an arbitrary 8-bit value. Characters are not supported
4.47 - // as a normal storage class; they may only be used for arrays. When read
4.48 - // from an array, they are immediately sign extended to 32 bits. Integers
4.49 - // stored into an char array are truncated to 8 bits.
4.50 - PrimitiveType_Char, // signed, 8-bit character
4.51 -
4.52 - // Enumerations and untyped variables are stored as signed, 32-bit integers.
4.53 - PrimitiveType_Int32,
4.54 -
4.55 - // Floating point values are 32-bit IEEE-754 floats. This is required ro
4.56 - // SourcePawn 1 compatibility.
4.57 - PrimitiveType_Float,
4.58 -
4.59 - // This is a native-sized integer type (32-bit on 32-bit systems, 64-bit
4.60 - // on 64-bit systems), and does not exist in language semantics.
4.61 - PrimitiveType_Native,
4.62 -
4.63 - PrimitiveTypes_Total
4.64 -};
4.65 -
4.66 -class Type : public Object
4.67 -{
4.68 - protected:
4.69 - enum Kind {
4.70 - // A primitive is a plain-old-data type.
4.71 - PRIMITIVE,
4.72 -
4.73 - // Void is an internal type used to specify that a function returns no
4.74 - // value.
4.75 - VOID,
4.76 -
4.77 - // Enums are plain-old-data with int32 storage. They allow for extra
4.78 - // type checking that would not be possible with integers.
4.79 - ENUM,
4.80 -
4.81 - // Unchecked is a magic type that has implicit, bitwise coercion to
4.82 - // int32, float, bool, or an enum.
4.83 - UNCHECKED,
4.84 -
4.85 - // ------ Add traceable types below -------
4.86 -
4.87 - // An immutable type that is a primitive in terms of language
4.88 - // semantics, but gets a special type here to make internal
4.89 - // logic easier.
4.90 - STRING,
4.91 -
4.92 - // An array is a fixed-length vector of any other type.
4.93 - ARRAY,
4.94 - EXTERNAL_ARRAY,
4.95 -
4.96 - // A reference type may only be specified on parameters, and
4.97 - // references may only be computed to primitives or enums.
4.98 - REFERENCE,
4.99 -
4.100 - // A function type encapsulates a function signature.
4.101 - FUNCTION,
4.102 -
4.103 - // Structs are composite records that may contain primitives, arrays,
4.104 - // functions, enums, and other structs.
4.105 - STRUCT
4.106 - };
4.107 -
4.108 - private:
4.109 - Kind kind() {
4.110 - return kind_;
4.111 - }
4.112 -
4.113 - public:
4.114 - static Type *NewVoid(Zone *zone);
4.115 - static Type *NewUnchecked(Zone *zone);
4.116 - static Type *NewPrimitive(Zone *zone, PrimitiveType type);
4.117 - static Type *NewString(Zone *zone);
4.118 -
4.119 - static Type *cast(Object *obj) {
4.120 - assert(!obj ||
4.121 - obj->is(MapKind_Type) ||
4.122 - obj->is(MapKind_FunctionType) ||
4.123 - obj->is(MapKind_StructType) ||
4.124 - obj->is(MapKind_ArrayType) ||
4.125 - obj->is(MapKind_ReferenceType) ||
4.126 - obj->is(MapKind_EnumType));
4.127 - return (Type *)obj;
4.128 - }
4.129 -
4.130 - bool isPrimitive() {
4.131 - return kind() == PRIMITIVE;
4.132 - }
4.133 - bool isArray() {
4.134 - return kind() == ARRAY || kind() == EXTERNAL_ARRAY;
4.135 - }
4.136 - bool isReference() {
4.137 - return kind() == REFERENCE;
4.138 - }
4.139 - bool isFunction() {
4.140 - return kind() == FUNCTION;
4.141 - }
4.142 - bool isVoid() {
4.143 - return kind() == VOID;
4.144 - }
4.145 - bool isUnchecked() {
4.146 - return kind() == UNCHECKED;
4.147 - }
4.148 - bool isStruct() {
4.149 - return kind() == STRUCT;
4.150 - }
4.151 - PrimitiveType primitive() {
4.152 - assert(isPrimitive());
4.153 - return primitive_;
4.154 - }
4.155 - bool isPod() {
4.156 - return (isPrimitive() && !isString()) || isEnum() || isUnchecked();
4.157 - }
4.158 - PrimitiveType pod() {
4.159 - assert(isPod());
4.160 - return isPrimitive()
4.161 - ? (primitive() == PrimitiveType_Bool)
4.162 - ? PrimitiveType_Int32
4.163 - : primitive()
4.164 - : PrimitiveType_Int32;
4.165 - }
4.166 - bool isChar() {
4.167 - return isPrimitive() && primitive() == PrimitiveType_Char;
4.168 - }
4.169 - bool isFloat() {
4.170 - return isPrimitive() && primitive() == PrimitiveType_Float;
4.171 - }
4.172 - bool isInt32() {
4.173 - return isPrimitive() && primitive() == PrimitiveType_Int32;
4.174 - }
4.175 - bool isInt32OrEnum() {
4.176 - return isInt32() || isEnum();
4.177 - }
4.178 - bool isBool() {
4.179 - return isPrimitive() && primitive() == PrimitiveType_Bool;
4.180 - }
4.181 - bool isString() {
4.182 - return kind() == STRING;
4.183 - }
4.184 - bool isExternalArray() {
4.185 - return kind() == EXTERNAL_ARRAY;
4.186 - }
4.187 - bool isTraceable() {
4.188 - return kind_ >= STRING;
4.189 - }
4.190 - bool isConst() {
4.191 - assert(isPrimitive() ||
4.192 - isArray() ||
4.193 - isReference());
4.194 - return const_;
4.195 - }
4.196 - bool isEnum() {
4.197 - return kind() == ENUM;
4.198 - }
4.199 -
4.200 - protected:
4.201 - Kind kind_;
4.202 - PrimitiveType primitive_;
4.203 -
4.204 - // Primitives, arrays, and references.
4.205 - bool const_;
4.206 -};
4.207 -
4.208 -class EnumType : public Type
4.209 -{
4.210 - public:
4.211 - static EnumType *New(Zone *Zone, Handle<String> name);
4.212 -
4.213 - String *name() {
4.214 - return name_;
4.215 - }
4.216 -
4.217 - // GC Descriptor.
4.218 - static inline size_t offsetOfName() {
4.219 - return OFFSETOF(EnumType, name_);
4.220 - }
4.221 - // End GC Descriptor.
4.222 -
4.223 - static EnumType *cast(Object *obj) {
4.224 - assert(!obj || obj->is(MapKind_EnumType));
4.225 - return (EnumType *)obj;
4.226 - }
4.227 -
4.228 - private:
4.229 - Barriered<String> name_;
4.230 -};
4.231 -
4.232 -class ReferenceType : public Type
4.233 -{
4.234 - public:
4.235 - static ReferenceType *New(Zone *zone, Handle<Type> contained);
4.236 -
4.237 - Type *contained() {
4.238 - return contained_;
4.239 - }
4.240 -
4.241 - // GC Descriptor.
4.242 - static inline size_t offsetOfContained() {
4.243 - return OFFSETOF(ReferenceType, contained_);
4.244 - }
4.245 - // End GC Descriptor.
4.246 -
4.247 - static ReferenceType *cast(Object *obj) {
4.248 - assert(!obj || obj->is(MapKind_ReferenceType));
4.249 - return (ReferenceType *)obj;
4.250 - }
4.251 -
4.252 - private:
4.253 - Barriered<Type> contained_;
4.254 -};
4.255 -
4.256 -class ArrayType : public Type
4.257 -{
4.258 - public:
4.259 - static const int DYNAMIC_ARRAY_SIZE = -1;
4.260 -
4.261 - static ArrayType *New(Zone *zone, Handle<Type> contained, int elements);
4.262 - static ArrayType *NewExternal(Zone *zone, Handle<Type> contained);
4.263 -
4.264 - Type *innermost() {
4.265 - Type *temp = contained();
4.266 - while (temp->isArray())
4.267 - temp = ArrayType::cast(temp)->contained();
4.268 - return temp;
4.269 - }
4.270 -
4.271 - Type *contained() {
4.272 - return contained_;
4.273 - }
4.274 - bool isFixedLength() {
4.275 - return elements_ > 0;
4.276 - }
4.277 - bool isCharArray() {
4.278 - return contained()->isPrimitive() &&
4.279 - contained()->primitive() == PrimitiveType_Char;
4.280 - }
4.281 - unsigned fixedLength() {
4.282 - assert(isFixedLength());
4.283 - return elements_;
4.284 - }
4.285 - unsigned levels() {
4.286 - return levels_;
4.287 - }
4.288 - bool hasInlineElements() {
4.289 - // We don't allocate traceable elements inline, since there's no
4.290 - // point to the optimization; we're going to be allocating lots of
4.291 - // objects anyway (in theory).
4.292 - return isFixedLength() && !contained()->isTraceable();
4.293 - }
4.294 -
4.295 - // Arrays of this type can be created with this cached map.
4.296 - ArrayMap *newMap() {
4.297 - return newMap_;
4.298 - }
4.299 - void setNewMap(ArrayMap *map) {
4.300 - assert(!newMap());
4.301 - newMap_ = map;
4.302 - }
4.303 -
4.304 - // GC Descriptor.
4.305 - static inline size_t offsetOfContained() {
4.306 - return OFFSETOF(ArrayType, contained_);
4.307 - }
4.308 - static inline size_t offsetOfNewMap() {
4.309 - return OFFSETOF(ArrayType, newMap_);
4.310 - }
4.311 - // End GC Descriptor.
4.312 -
4.313 - static ArrayType *cast(Object *obj) {
4.314 - assert(!obj || obj->is(MapKind_ArrayType));
4.315 - return (ArrayType *)obj;
4.316 - }
4.317 -
4.318 - private:
4.319 - int32 elements_;
4.320 - unsigned levels_;
4.321 - Barriered<Type> contained_;
4.322 - Barriered<ArrayMap> newMap_;
4.323 -};
4.324 -
4.325 -class StructType : public Type
4.326 -{
4.327 - public:
4.328 - static StructType *New(Zone *zone, Handle<String> name, Handle<FixedArray> fields);
4.329 -
4.330 - FixedArray *fields() {
4.331 - assert(isStruct());
4.332 - return fields_;
4.333 - }
4.334 - Descriptor *lookupField(Handle<String> name, unsigned *index = NULL);
4.335 -
4.336 - // Objects of this type can be created with this cached map.
4.337 - StructMap *newMap() {
4.338 - return newMap_;
4.339 - }
4.340 - void setNewMap(StructMap *map) {
4.341 - assert(!newMap());
4.342 - newMap_ = map;
4.343 - }
4.344 -
4.345 - String *name() {
4.346 - return name_;
4.347 - }
4.348 -
4.349 - // GC Descriptor.
4.350 - static inline size_t offsetOfFields() {
4.351 - return OFFSETOF(StructType, fields_);
4.352 - }
4.353 - static inline size_t offsetOfNewMap() {
4.354 - return OFFSETOF(StructType, newMap_);
4.355 - }
4.356 - static inline size_t offsetOfName() {
4.357 - return OFFSETOF(StructType, name_);
4.358 - }
4.359 - // End GC Descriptor.
4.360 -
4.361 - static StructType *cast(Object *obj) {
4.362 - assert(!obj || obj->is(MapKind_StructType));
4.363 - return (StructType *)obj;
4.364 - }
4.365 -
4.366 - private:
4.367 - // Structs only.
4.368 - Barriered<FixedArray> fields_;
4.369 - Barriered<StructMap> newMap_;
4.370 - Barriered<String> name_;
4.371 -};
4.372 -
4.373 -class FunctionType : public Type
4.374 -{
4.375 - public:
4.376 - static FunctionType *New(Zone *zone, Handle<String> name, TokenKind kind);
4.377 -
4.378 - Type *parameterAt(size_t i) {
4.379 - return Type::cast(parameters()->at(i));
4.380 - }
4.381 - Type *returnType() {
4.382 - assert(isFunction());
4.383 - return returnType_;
4.384 - }
4.385 - FixedArray *parameters() {
4.386 - assert(isFunction());
4.387 - return parameters_;
4.388 - }
4.389 - FixedArray *defaults() {
4.390 - assert(isFunction());
4.391 - return defaults_;
4.392 - }
4.393 - bool isNative() {
4.394 - return token_ == TOK_NATIVE;
4.395 - }
4.396 - bool isForward() {
4.397 - return token_ == TOK_FORWARD;
4.398 - }
4.399 - bool isNativeVariadic() {
4.400 - assert(isNative());
4.401 - return variadicNative_;
4.402 - }
4.403 - void setReturnType(Handle<Type> returnType) {
4.404 - assert(!returnType_);
4.405 - returnType_ = returnType;
4.406 - }
4.407 - void setParameterTypes(Handle<FixedArray> types) {
4.408 - assert(!parameters_);
4.409 - parameters_ = types;
4.410 - }
4.411 - TokenKind token() {
4.412 - return token_;
4.413 - }
4.414 - String *name() {
4.415 - return name_;
4.416 - }
4.417 -
4.418 - // GC Descriptor.
4.419 - static inline size_t offsetOfReturnType() {
4.420 - return OFFSETOF(FunctionType, returnType_);
4.421 - }
4.422 - static inline size_t offsetOfParameters() {
4.423 - return OFFSETOF(FunctionType, parameters_);
4.424 - }
4.425 - static inline size_t offsetOfDefaults() {
4.426 - return OFFSETOF(FunctionType, defaults_);
4.427 - }
4.428 - static inline size_t offsetOfName() {
4.429 - return OFFSETOF(FunctionType, name_);
4.430 - }
4.431 - // End GC Descriptor.
4.432 -
4.433 - static FunctionType *cast(Object *obj) {
4.434 - assert(!obj || obj->is(MapKind_FunctionType));
4.435 - return (FunctionType *)obj;
4.436 - }
4.437 -
4.438 - private:
4.439 - // Functions only.
4.440 - Barriered<Type> returnType_;
4.441 - Barriered<FixedArray> parameters_;
4.442 - Barriered<FixedArray> defaults_;
4.443 - Barriered<String> name_;
4.444 - TokenKind token_;
4.445 - bool variadicNative_;
4.446 -};
4.447 -
4.448 -class BoxedPrimitive
4.449 -{
4.450 - PrimitiveType type_;
4.451 - union {
4.452 - int i_;
4.453 - float f_;
4.454 - };
4.455 -
4.456 - public:
4.457 - static BoxedPrimitive Int(int i) {
4.458 - BoxedPrimitive b;
4.459 - b.type_ = PrimitiveType_Int32;
4.460 - b.i_ = i;
4.461 - return b;
4.462 - }
4.463 - static BoxedPrimitive Float(float f) {
4.464 - BoxedPrimitive b;
4.465 - b.type_ = PrimitiveType_Float;
4.466 - b.f_ = f;
4.467 - return b;
4.468 - }
4.469 -
4.470 - PrimitiveType type() const {
4.471 - return type_;
4.472 - }
4.473 - int toInt() const {
4.474 - assert(type() == PrimitiveType_Int32);
4.475 - return i_;
4.476 - }
4.477 - float toFloat() const {
4.478 - assert(type() == PrimitiveType_Float);
4.479 - return f_;
4.480 - }
4.481 -};
4.482 -
4.483 -const char *GetTypeName(Type *type);
4.484 -
4.485 -}
4.486 -
4.487 -#endif // _include_jc_types_h_
4.488 +/* vim: set ts=4 sw=4 tw=99 et:
4.489 + *
4.490 + * Copyright (C) 2012 David Anderson
4.491 + *
4.492 + * This file is part of JITCraft.
4.493 + *
4.494 + * JITCraft is free software: you can redistribute it and/or modify it under
4.495 + * the terms of the GNU General Public License as published by the Free
4.496 + * Software Foundation, either version 3 of the License, or (at your option)
4.497 + * any later version.
4.498 + *
4.499 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
4.500 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
4.501 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
4.502 + *
4.503 + * You should have received a copy of the GNU General Public License along with
4.504 + * JITCraft. If not, see http://www.gnu.org/licenses/.
4.505 + */
4.506 +#ifndef _include_jc_types_h_
4.507 +#define _include_jc_types_h_
4.508 +
4.509 +#include "Heap.h"
4.510 +#include "Barriers.h"
4.511 +#include "FixedArray.h"
4.512 +#include "compiler/Token.h"
4.513 +
4.514 +namespace ke {
4.515 +
4.516 +class String;
4.517 +class Descriptor;
4.518 +class StructMap;
4.519 +class ArrayMap;
4.520 +
4.521 +#define MAX_ARRAY_DEPTH 5
4.522 +
4.523 +enum PrimitiveType
4.524 +{
4.525 + // A boolean type semantically represents 0 or 1. As an optimization, its
4.526 + // internal storage type is the same as int32, and any non-zero value
4.527 + // compares positively to "true".
4.528 + PrimitiveType_Bool,
4.529 +
4.530 + // A character is an arbitrary 8-bit value. Characters are not supported
4.531 + // as a normal storage class; they may only be used for arrays. When read
4.532 + // from an array, they are immediately sign extended to 32 bits. Integers
4.533 + // stored into an char array are truncated to 8 bits.
4.534 + PrimitiveType_Char, // signed, 8-bit character
4.535 +
4.536 + // Enumerations and untyped variables are stored as signed, 32-bit integers.
4.537 + PrimitiveType_Int32,
4.538 +
4.539 + // Floating point values are 32-bit IEEE-754 floats. This is required ro
4.540 + // SourcePawn 1 compatibility.
4.541 + PrimitiveType_Float,
4.542 +
4.543 + // This is a native-sized integer type (32-bit on 32-bit systems, 64-bit
4.544 + // on 64-bit systems), and does not exist in language semantics.
4.545 + PrimitiveType_Native,
4.546 +
4.547 + PrimitiveTypes_Total
4.548 +};
4.549 +
4.550 +enum TypeQualifiers
4.551 +{
4.552 + TypeQual_None = 0,
4.553 +
4.554 + // Const qualifier that has not been determined yet.
4.555 + TypeQual_UnkConst = (1 << 0),
4.556 +
4.557 + // For simplification, SP2 differentiates between two meanings of const.
4.558 + // "StoreConst" means that the value itself may not be changed. For
4.559 + // example,
4.560 + // const a = 5;
4.561 + //
4.562 + // Specifies that the storage of "a" is immutable.
4.563 + //
4.564 + // In addition, "RefConst" means that the memory at a reference may not
4.565 + // be changed. For example,
4.566 + //
4.567 + // const char:text[] = "asdfasdfasdf";
4.568 + //
4.569 + // Specifies a readonly view of a character array, however, |text| itself
4.570 + // may be repointed to another readonly character array.
4.571 + //
4.572 + // The meaning of "const" is inferred based on the scope and type:
4.573 + //
4.574 + // +---------+---------+-------+
4.575 + // | Array | Struct | Other |
4.576 + // +---------------+---------+---------+-------+
4.577 + // | GLOBAL/STATIC | Ref|Str | Ref|Str | Str |
4.578 + // | LOCAL | Ref | Ref|Str | Str |
4.579 + // +---------------+---------+---------+-------+
4.580 + TypeQual_StoreConst = (1 << 1),
4.581 + TypeQual_RefConst = (1 << 2)
4.582 +};
4.583 +
4.584 +class Type : public Object
4.585 +{
4.586 + protected:
4.587 + enum Kind {
4.588 + // A primitive is a plain-old-data type.
4.589 + PRIMITIVE,
4.590 +
4.591 + // Void is an internal type used to specify that a function returns no
4.592 + // value.
4.593 + VOID,
4.594 +
4.595 + // Enums are plain-old-data with int32 storage. They allow for extra
4.596 + // type checking that would not be possible with integers.
4.597 + ENUM,
4.598 +
4.599 + // Unchecked is a magic type that has implicit, bitwise coercion to
4.600 + // int32, float, bool, or an enum.
4.601 + UNCHECKED,
4.602 +
4.603 + // ------ Add traceable types below -------
4.604 +
4.605 + // An immutable type that is a primitive in terms of language
4.606 + // semantics, but gets a special type here to make internal
4.607 + // logic easier.
4.608 + STRING,
4.609 +
4.610 + // An array is a fixed-length vector of any other type.
4.611 + ARRAY,
4.612 + EXTERNAL_ARRAY,
4.613 +
4.614 + // A reference type may only be specified on parameters, and
4.615 + // references may only be computed to primitives or enums.
4.616 + REFERENCE,
4.617 +
4.618 + // A function type encapsulates a function signature.
4.619 + FUNCTION,
4.620 +
4.621 + // Structs are composite records that may contain primitives, arrays,
4.622 + // functions, enums, and other structs.
4.623 + STRUCT,
4.624 +
4.625 + // Contains type qualifiers, and a back pointer to the actual
4.626 + // unqualified type.
4.627 + QUALTYPE
4.628 + };
4.629 +
4.630 + void init(Kind kind);
4.631 +
4.632 + private:
4.633 + Kind kind() {
4.634 + return root_->kind_;
4.635 + }
4.636 +
4.637 + public:
4.638 + static Type *NewVoid(Zone *zone);
4.639 + static Type *NewUnchecked(Zone *zone);
4.640 + static Type *NewPrimitive(Zone *zone, PrimitiveType type);
4.641 + static Type *NewString(Zone *zone);
4.642 +
4.643 + static Type *cast(Object *obj) {
4.644 + assert(!obj ||
4.645 + obj->is(MapKind_Type) ||
4.646 + obj->is(MapKind_FunctionType) ||
4.647 + obj->is(MapKind_StructType) ||
4.648 + obj->is(MapKind_ArrayType) ||
4.649 + obj->is(MapKind_ReferenceType) ||
4.650 + obj->is(MapKind_EnumType));
4.651 + return (Type *)obj;
4.652 + }
4.653 +
4.654 + bool isPrimitive() {
4.655 + return kind() == PRIMITIVE;
4.656 + }
4.657 + bool isArray() {
4.658 + return kind() == ARRAY || kind() == EXTERNAL_ARRAY;
4.659 + }
4.660 + bool isReference() {
4.661 + return kind() == REFERENCE;
4.662 + }
4.663 + bool isFunction() {
4.664 + return kind() == FUNCTION;
4.665 + }
4.666 + bool isVoid() {
4.667 + return kind() == VOID;
4.668 + }
4.669 + bool isUnchecked() {
4.670 + return kind() == UNCHECKED;
4.671 + }
4.672 + bool isStruct() {
4.673 + return kind() == STRUCT;
4.674 + }
4.675 + PrimitiveType primitive() {
4.676 + assert(isPrimitive());
4.677 + return root_->primitive_;
4.678 + }
4.679 + bool isPod() {
4.680 + return (isPrimitive() && !isString()) || isEnum() || isUnchecked();
4.681 + }
4.682 + PrimitiveType pod() {
4.683 + assert(isPod());
4.684 + return isPrimitive()
4.685 + ? (primitive() == PrimitiveType_Bool)
4.686 + ? PrimitiveType_Int32
4.687 + : primitive()
4.688 + : PrimitiveType_Int32;
4.689 + }
4.690 + bool isChar() {
4.691 + return isPrimitive() && primitive() == PrimitiveType_Char;
4.692 + }
4.693 + bool isFloat() {
4.694 + return isPrimitive() && primitive() == PrimitiveType_Float;
4.695 + }
4.696 + bool isInt32() {
4.697 + return isPrimitive() && primitive() == PrimitiveType_Int32;
4.698 + }
4.699 + bool isInt32OrEnum() {
4.700 + return isInt32() || isEnum();
4.701 + }
4.702 + bool isBool() {
4.703 + return isPrimitive() && primitive() == PrimitiveType_Bool;
4.704 + }
4.705 + bool isString() {
4.706 + return kind() == STRING;
4.707 + }
4.708 + bool isExternalArray() {
4.709 + return kind() == EXTERNAL_ARRAY;
4.710 + }
4.711 + bool isTraceable() {
4.712 + return kind() >= STRING;
4.713 + }
4.714 + bool isEnum() {
4.715 + return kind() == ENUM;
4.716 + }
4.717 + bool hasTypeQualifiers() {
4.718 + return kind_ == QUALTYPE;
4.719 + }
4.720 +
4.721 + TypeQualifiers quals() {
4.722 + if (hasTypeQualifiers())
4.723 + return TypeQual_None;
4.724 + return quals_;
4.725 + }
4.726 +
4.727 + // GC Descriptor.
4.728 + static inline size_t offsetOfRoot() {
4.729 + return OFFSETOF(Type, root_);
4.730 + }
4.731 + // End GC Descriptor.
4.732 +
4.733 + protected:
4.734 + Kind kind_;
4.735 + PrimitiveType primitive_;
4.736 + TypeQualifiers quals_;
4.737 +
4.738 + // For unqualified types, this points to |this|. For qualified types, it
4.739 + // points to the unqualified original type.
4.740 + Barriered<Type> root_;
4.741 +};
4.742 +
4.743 +class EnumType : public Type
4.744 +{
4.745 + public:
4.746 + static EnumType *New(Zone *Zone, Handle<String> name);
4.747 +
4.748 + String *name() {
4.749 + return name_;
4.750 + }
4.751 +
4.752 + // GC Descriptor.
4.753 + static inline size_t offsetOfName() {
4.754 + return OFFSETOF(EnumType, name_);
4.755 + }
4.756 + // End GC Descriptor.
4.757 +
4.758 + static EnumType *cast(Object *obj) {
4.759 + assert(!obj || obj->is(MapKind_EnumType));
4.760 + return (EnumType *)obj;
4.761 + }
4.762 +
4.763 + private:
4.764 + Barriered<String> name_;
4.765 +};
4.766 +
4.767 +class ReferenceType : public Type
4.768 +{
4.769 + public:
4.770 + static ReferenceType *New(Zone *zone, Handle<Type> contained);
4.771 +
4.772 + Type *contained() {
4.773 + return contained_;
4.774 + }
4.775 +
4.776 + // GC Descriptor.
4.777 + static inline size_t offsetOfContained() {
4.778 + return OFFSETOF(ReferenceType, contained_);
4.779 + }
4.780 + // End GC Descriptor.
4.781 +
4.782 + static ReferenceType *cast(Object *obj) {
4.783 + assert(!obj || obj->is(MapKind_ReferenceType));
4.784 + return (ReferenceType *)obj;
4.785 + }
4.786 +
4.787 + private:
4.788 + Barriered<Type> contained_;
4.789 +};
4.790 +
4.791 +class ArrayType : public Type
4.792 +{
4.793 + public:
4.794 + static const int DYNAMIC_ARRAY_SIZE = -1;
4.795 +
4.796 + static ArrayType *New(Zone *zone, Handle<Type> contained, int elements);
4.797 + static ArrayType *NewExternal(Zone *zone, Handle<Type> contained);
4.798 +
4.799 + Type *innermost() {
4.800 + Type *temp = contained();
4.801 + while (temp->isArray())
4.802 + temp = ArrayType::cast(temp)->contained();
4.803 + return temp;
4.804 + }
4.805 +
4.806 + Type *contained() {
4.807 + return contained_;
4.808 + }
4.809 + bool isFixedLength() {
4.810 + return elements_ > 0;
4.811 + }
4.812 + bool isCharArray() {
4.813 + return contained()->isPrimitive() &&
4.814 + contained()->primitive() == PrimitiveType_Char;
4.815 + }
4.816 + unsigned fixedLength() {
4.817 + assert(isFixedLength());
4.818 + return elements_;
4.819 + }
4.820 + unsigned levels() {
4.821 + return levels_;
4.822 + }
4.823 + bool hasInlineElements() {
4.824 + // We don't allocate traceable elements inline, since there's no
4.825 + // point to the optimization; we're going to be allocating lots of
4.826 + // objects anyway (in theory).
4.827 + return isFixedLength() && !contained()->isTraceable();
4.828 + }
4.829 +
4.830 + // Arrays of this type can be created with this cached map.
4.831 + ArrayMap *newMap() {
4.832 + return newMap_;
4.833 + }
4.834 + void setNewMap(ArrayMap *map) {
4.835 + assert(!newMap());
4.836 + newMap_ = map;
4.837 + }
4.838 +
4.839 + // GC Descriptor.
4.840 + static inline size_t offsetOfContained() {
4.841 + return OFFSETOF(ArrayType, contained_);
4.842 + }
4.843 + static inline size_t offsetOfNewMap() {
4.844 + return OFFSETOF(ArrayType, newMap_);
4.845 + }
4.846 + // End GC Descriptor.
4.847 +
4.848 + static ArrayType *cast(Object *obj) {
4.849 + assert(!obj || obj->is(MapKind_ArrayType));
4.850 + return (ArrayType *)obj;
4.851 + }
4.852 +
4.853 + private:
4.854 + int32 elements_;
4.855 + unsigned levels_;
4.856 + Barriered<Type> contained_;
4.857 + Barriered<ArrayMap> newMap_;
4.858 +};
4.859 +
4.860 +class StructType : public Type
4.861 +{
4.862 + public:
4.863 + static StructType *New(Zone *zone, Handle<String> name, Handle<FixedArray> fields);
4.864 +
4.865 + FixedArray *fields() {
4.866 + assert(isStruct());
4.867 + return fields_;
4.868 + }
4.869 + Descriptor *lookupField(Handle<String> name, unsigned *index = NULL);
4.870 +
4.871 + // Objects of this type can be created with this cached map.
4.872 + StructMap *newMap() {
4.873 + return newMap_;
4.874 + }
4.875 + void setNewMap(StructMap *map) {
4.876 + assert(!newMap());
4.877 + newMap_ = map;
4.878 + }
4.879 +
4.880 + String *name() {
4.881 + return name_;
4.882 + }
4.883 +
4.884 + // GC Descriptor.
4.885 + static inline size_t offsetOfFields() {
4.886 + return OFFSETOF(StructType, fields_);
4.887 + }
4.888 + static inline size_t offsetOfNewMap() {
4.889 + return OFFSETOF(StructType, newMap_);
4.890 + }
4.891 + static inline size_t offsetOfName() {
4.892 + return OFFSETOF(StructType, name_);
4.893 + }
4.894 + // End GC Descriptor.
4.895 +
4.896 + static StructType *cast(Object *obj) {
4.897 + assert(!obj || obj->is(MapKind_StructType));
4.898 + return (StructType *)obj;
4.899 + }
4.900 +
4.901 + private:
4.902 + // Structs only.
4.903 + Barriered<FixedArray> fields_;
4.904 + Barriered<StructMap> newMap_;
4.905 + Barriered<String> name_;
4.906 +};
4.907 +
4.908 +class FunctionType : public Type
4.909 +{
4.910 + public:
4.911 + static FunctionType *New(Zone *zone, Handle<String> name, TokenKind kind);
4.912 +
4.913 + Type *parameterAt(size_t i) {
4.914 + return Type::cast(parameters()->at(i));
4.915 + }
4.916 + Type *returnType() {
4.917 + assert(isFunction());
4.918 + return returnType_;
4.919 + }
4.920 + FixedArray *parameters() {
4.921 + assert(isFunction());
4.922 + return parameters_;
4.923 + }
4.924 + FixedArray *defaults() {
4.925 + assert(isFunction());
4.926 + return defaults_;
4.927 + }
4.928 + bool isNative() {
4.929 + return token_ == TOK_NATIVE;
4.930 + }
4.931 + bool isForward() {
4.932 + return token_ == TOK_FORWARD;
4.933 + }
4.934 + bool isNativeVariadic() {
4.935 + assert(isNative());
4.936 + return variadicNative_;
4.937 + }
4.938 + void setReturnType(Handle<Type> returnType) {
4.939 + assert(!returnType_);
4.940 + returnType_ = returnType;
4.941 + }
4.942 + void setParameterTypes(Handle<FixedArray> types) {
4.943 + assert(!parameters_);
4.944 + parameters_ = types;
4.945 + }
4.946 + TokenKind token() {
4.947 + return token_;
4.948 + }
4.949 + String *name() {
4.950 + return name_;
4.951 + }
4.952 +
4.953 + // GC Descriptor.
4.954 + static inline size_t offsetOfReturnType() {
4.955 + return OFFSETOF(FunctionType, returnType_);
4.956 + }
4.957 + static inline size_t offsetOfParameters() {
4.958 + return OFFSETOF(FunctionType, parameters_);
4.959 + }
4.960 + static inline size_t offsetOfDefaults() {
4.961 + return OFFSETOF(FunctionType, defaults_);
4.962 + }
4.963 + static inline size_t offsetOfName() {
4.964 + return OFFSETOF(FunctionType, name_);
4.965 + }
4.966 + // End GC Descriptor.
4.967 +
4.968 + static FunctionType *cast(Object *obj) {
4.969 + assert(!obj || obj->is(MapKind_FunctionType));
4.970 + return (FunctionType *)obj;
4.971 + }
4.972 +
4.973 + private:
4.974 + // Functions only.
4.975 + Barriered<Type> returnType_;
4.976 + Barriered<FixedArray> parameters_;
4.977 + Barriered<FixedArray> defaults_;
4.978 + Barriered<String> name_;
4.979 + TokenKind token_;
4.980 + bool variadicNative_;
4.981 +};
4.982 +
4.983 +class BoxedPrimitive
4.984 +{
4.985 + PrimitiveType type_;
4.986 + union {
4.987 + int i_;
4.988 + float f_;
4.989 + };
4.990 +
4.991 + public:
4.992 + static BoxedPrimitive Int(int i) {
4.993 + BoxedPrimitive b;
4.994 + b.type_ = PrimitiveType_Int32;
4.995 + b.i_ = i;
4.996 + return b;
4.997 + }
4.998 + static BoxedPrimitive Float(float f) {
4.999 + BoxedPrimitive b;
4.1000 + b.type_ = PrimitiveType_Float;
4.1001 + b.f_ = f;
4.1002 + return b;
4.1003 + }
4.1004 +
4.1005 + PrimitiveType type() const {
4.1006 + return type_;
4.1007 + }
4.1008 + int toInt() const {
4.1009 + assert(type() == PrimitiveType_Int32);
4.1010 + return i_;
4.1011 + }
4.1012 + float toFloat() const {
4.1013 + assert(type() == PrimitiveType_Float);
4.1014 + return f_;
4.1015 + }
4.1016 +};
4.1017 +
4.1018 +const char *GetTypeName(Type *type);
4.1019 +
4.1020 +}
4.1021 +
4.1022 +#endif // _include_jc_types_h_
5.1 --- a/src/compiler/AST.h Mon Dec 24 16:43:22 2012 -0800
5.2 +++ b/src/compiler/AST.h Tue Dec 25 16:32:06 2012 -0800
5.3 @@ -24,7 +24,6 @@
5.4 #include "Token.h"
5.5 #include "NameBinding.h"
5.6 #include "Symbols.h"
5.7 -#include "../QualType.h"
5.8
5.9 namespace ke {
5.10
6.1 --- a/src/compiler/Parser.cpp Mon Dec 24 16:43:22 2012 -0800
6.2 +++ b/src/compiler/Parser.cpp Tue Dec 25 16:32:06 2012 -0800
6.3 @@ -804,7 +804,7 @@
6.4 Statement *decl = NULL;
6.5 if (!match(TOK_SEMICOLON)) {
6.6 if (match(TOK_NEW)) {
6.7 - if ((decl = vars(Qual_None)) == NULL)
6.8 + if ((decl = vars(TypeQual_None)) == NULL)
6.9 return NULL;
6.10 } else {
6.11 if ((decl = expressionStatement()) == NULL)
6.12 @@ -1044,8 +1044,8 @@
6.13 case TOK_NEW:
6.14 {
6.15 TypeQualifiers quals = (kind == TOK_CONST)
6.16 - ? Qual_Const
6.17 - : Qual_None;
6.18 + ? TypeQual_UnkConst
6.19 + : TypeQual_None;
6.20 scanner_.scan();
6.21 if ((statement = vars(quals)) == NULL)
6.22 return NULL;
6.23 @@ -1412,8 +1412,7 @@
6.24 if (kind != TOK_LABEL)
6.25 scanner_.scan();
6.26 if (kind == TOK_PUBLIC && peek(TOK_CONST)) {
6.27 - TypeQualifiers quals = TypeQualifiers(Qual_Public | Qual_Const);
6.28 - if ((statement = var(quals)) == NULL)
6.29 + if ((statement = var(TypeQual_UnkConst)) == NULL)
6.30 return NULL;
6.31 if (!matchSemicolon())
6.32 return NULL;
6.33 @@ -1429,7 +1428,7 @@
6.34 case TOK_CONST:
6.35 case TOK_NEW:
6.36 {
6.37 - TypeQualifiers quals = (kind == TOK_NEW) ? Qual_Const : Qual_None;
6.38 + TypeQualifiers quals = (kind == TOK_NEW) ? TypeQual_UnkConst : TypeQual_None;
6.39 // Note: at global scope, we don't accept comma-delimited
6.40 // declarations yet, to see if we can get away with forcing
6.41 // a nicer top-level style.
7.1 --- a/src/compiler/SemanticAnalysis.cpp Mon Dec 24 16:43:22 2012 -0800
7.2 +++ b/src/compiler/SemanticAnalysis.cpp Tue Dec 25 16:32:06 2012 -0800
7.3 @@ -888,7 +888,7 @@
7.4 // We treat declaration separately from assignment, since for
7.5 // declaration we can just immediately use the cloned version.
7.6 bool shouldDuplicate = true;
7.7 - if (actual->isConst() ||
7.8 + if (0 /*actual->isConst() :TODO */ ||
7.9 (actual->isFixedLength() && kind == Coerce_Assign))
7.10 {
7.11 shouldDuplicate = false;