Preparatory refactoring for const types.
authorDavid Anderson <dvander@alliedmods.net>
Tue Dec 25 16:32:06 2012 -0800 (2012-12-25)
changeset 238e9bec7549c28
parent 237 c77540a61905
child 239 572668ef742b
Preparatory refactoring for const types.
src/ObjectVisitor.h
src/QualType.h
src/Types.cpp
src/Types.h
src/compiler/AST.h
src/compiler/Parser.cpp
src/compiler/SemanticAnalysis.cpp
     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;