Re-add enum support.
authorDavid Anderson <dvander@alliedmods.net>
Sat Dec 22 23:18:57 2012 -0800 (2012-12-22)
changeset 233bbb498ccb4ac
parent 232 2b8512340180
child 234 26e3035cdffc
Re-add enum support.
src/Handles.h
src/Messages.tbl
src/ObjectVisitor.h
src/Objects.h
src/Opcodes.cpp
src/Platform-Windows.cpp
src/TypeManager.cpp
src/TypeManager.h
src/Types.cpp
src/Types.h
src/Zone.cpp
src/compiler/AST.h
src/compiler/NameBinding.cpp
src/compiler/Parser.cpp
src/compiler/SemanticAnalysis.cpp
src/compiler/SemanticAnalysis.h
src/compiler/Symbols.h
tests/basic/enum-bad.err
tests/basic/enum-bad.sp
tests/basic/enum-redecl.err
tests/basic/enum-redecl.sp
tests/basic/enum-use.out
tests/basic/enum-use.sp
     1.1 --- a/src/Handles.h	Sat Dec 22 19:48:43 2012 -0800
     1.2 +++ b/src/Handles.h	Sat Dec 22 23:18:57 2012 -0800
     1.3 @@ -85,6 +85,10 @@
     1.4          return (!thingp_ && !other.thingp_) ||
     1.5                 *thingp_ == *other.thingp_;
     1.6      }
     1.7 +    bool operator !=(const Handle<T> &other) const {
     1.8 +        return (!thingp_ != !other.thingp_) ||
     1.9 +               *thingp_ != *other.thingp_;
    1.10 +    }
    1.11  
    1.12    private:
    1.13      template <typename S>
     2.1 --- a/src/Messages.tbl	Sat Dec 22 19:48:43 2012 -0800
     2.2 +++ b/src/Messages.tbl	Sat Dec 22 23:18:57 2012 -0800
     2.3 @@ -33,8 +33,6 @@
     2.4  MSG(ArraySizeCannotBeDetermined,    SyntaxError,            "array size cannot be determined from initializer")
     2.5  MSG(ArrayAssignmentTooBig,          SyntaxError,            "destination array is too small")
     2.6  MSG(CannotDeclareStringCell,        SyntaxError,            "cannot declare a String cell")
     2.7 -MSG(BinaryTypeError,                SyntaxError,            "operator '%s' does not support types '%s' and '%s'")
     2.8 -MSG(UnaryTypeError,                 SyntaxError,            "operator '%s' does not support type '%s'")
     2.9  MSG(CantOpenFile,                   SyntaxError,            "cannot open file")
    2.10  MSG(ErrorSeekingFile,               SyntaxError,            "error seeking file")
    2.11  MSG(ErrorReadingFile,               SyntaxError,            "error reading file")
    2.12 @@ -80,4 +78,5 @@
    2.13  MSG(SizeofNeedsArray,               TypeError,              "sizeof requires an array")
    2.14  MSG(ImportsMustBeFirst,             SyntaxError,            "import statements must come before other statements")
    2.15  MSG(ImportedNameAlreadyBound,       TypeError,              "imported name has already been bound")
    2.16 -MSG(CannotResolveImport,            TypeError,              "cannot resolve import %s")
    2.17 \ No newline at end of file
    2.18 +MSG(CannotResolveImport,            TypeError,              "cannot resolve import %s")
    2.19 +MSG(InvalidCoercion,                TypeError,              "cannot coerce type '%s' to type '%s'")
    2.20 \ No newline at end of file
     3.1 --- a/src/ObjectVisitor.h	Sat Dec 22 19:48:43 2012 -0800
     3.2 +++ b/src/ObjectVisitor.h	Sat Dec 22 23:18:57 2012 -0800
     3.3 @@ -46,10 +46,14 @@
     3.4      }
     3.5  
     3.6      size_t iterateType(Object *obj) {
     3.7 -        visitField(obj, Type::offsetOfName());
     3.8          return sizeof(Type);
     3.9      }
    3.10  
    3.11 +    size_t iterateEnumType(Object *obj) {
    3.12 +        visitField(obj, EnumType::offsetOfName());
    3.13 +        return sizeof(EnumType);
    3.14 +    }
    3.15 +
    3.16      size_t iterateReferenceType(Object *obj) {
    3.17          iterateType(obj);
    3.18          visitField(obj, ReferenceType::offsetOfContained());
    3.19 @@ -67,6 +71,7 @@
    3.20          iterateType(obj);
    3.21          visitField(obj, StructType::offsetOfFields());
    3.22          visitField(obj, StructType::offsetOfNewMap());
    3.23 +        visitField(obj, StructType::offsetOfName());
    3.24          return sizeof(StructType);
    3.25      }
    3.26  
    3.27 @@ -75,6 +80,7 @@
    3.28          visitField(obj, FunctionType::offsetOfReturnType());
    3.29          visitField(obj, FunctionType::offsetOfParameters());      
    3.30          visitField(obj, FunctionType::offsetOfDefaults());
    3.31 +        visitField(obj, FunctionType::offsetOfName());
    3.32          return sizeof(FunctionType);
    3.33      }
    3.34  
    3.35 @@ -207,6 +213,9 @@
    3.36            case MapKind_ArrayType:
    3.37              return iterateArrayType(obj);
    3.38  
    3.39 +          case MapKind_EnumType:
    3.40 +            return iterateEnumType(obj);
    3.41 +
    3.42            case MapKind_FunctionType:
    3.43              return iterateFunctionType(obj);
    3.44  
    3.45 @@ -293,6 +302,9 @@
    3.46        case MapKind_ArrayType:
    3.47          return sizeof(ArrayType);
    3.48  
    3.49 +      case MapKind_EnumType:
    3.50 +        return sizeof(EnumType);
    3.51 +
    3.52        case MapKind_FunctionType:
    3.53          return sizeof(FunctionType);
    3.54  
     4.1 --- a/src/Objects.h	Sat Dec 22 19:48:43 2012 -0800
     4.2 +++ b/src/Objects.h	Sat Dec 22 23:18:57 2012 -0800
     4.3 @@ -39,6 +39,7 @@
     4.4      MapKind_StructType,
     4.5      MapKind_ArrayType,
     4.6      MapKind_ReferenceType,
     4.7 +    MapKind_EnumType,
     4.8  
     4.9      // Represents basic data structures. When adding to this, don't forget
    4.10      // to update Zone::initialize(), or you'll get a NULL crash trying to
     5.1 --- a/src/Opcodes.cpp	Sat Dec 22 19:48:43 2012 -0800
     5.2 +++ b/src/Opcodes.cpp	Sat Dec 22 23:18:57 2012 -0800
     5.3 @@ -256,7 +256,7 @@
     5.4            {
     5.5              Heap::Tenure tenure = (Heap::Tenure)pc[1];
     5.6              StructMap *map = StructMap::cast(code->map(READ_UINT32(pc + 1)));
     5.7 -            fprintf(fp, "%s", map->type()->name()->chars());
     5.8 +            fprintf(fp, "%s", StructType::cast(map->type())->name()->chars());
     5.9              if (tenure == Heap::Tenure_Stack)
    5.10                  fprintf(fp, " ; lifo");
    5.11              else if (tenure == Heap::Tenure_Old)
     6.1 --- a/src/Platform-Windows.cpp	Sat Dec 22 19:48:43 2012 -0800
     6.2 +++ b/src/Platform-Windows.cpp	Sat Dec 22 23:18:57 2012 -0800
     6.3 @@ -2,19 +2,19 @@
     6.4   *
     6.5   * Copyright (C) 2012 David Anderson
     6.6   *
     6.7 - * This file is part of JITCraft.
     6.8 + * This file is part of SourcePawn.
     6.9   *
    6.10 - * JITCraft is free software: you can redistribute it and/or modify it under
    6.11 + * SourcePawn is free software: you can redistribute it and/or modify it under
    6.12   * the terms of the GNU General Public License as published by the Free
    6.13   * Software Foundation, either version 3 of the License, or (at your option)
    6.14   * any later version.
    6.15   * 
    6.16 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    6.17 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    6.18   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    6.19   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    6.20   *
    6.21   * You should have received a copy of the GNU General Public License along with
    6.22 - * JITCraft. If not, see http://www.gnu.org/licenses/.
    6.23 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
    6.24   */
    6.25  
    6.26  // :TODO: move into utility-style include
     7.1 --- a/src/TypeManager.cpp	Sat Dec 22 19:48:43 2012 -0800
     7.2 +++ b/src/TypeManager.cpp	Sat Dec 22 23:18:57 2012 -0800
     7.3 @@ -64,20 +64,20 @@
     7.4      return true;
     7.5  }
     7.6  
     7.7 -Type *
     7.8 +ArrayType *
     7.9  TypeManager::newArray(Handle<Type> contained, int elements)
    7.10  {
    7.11      // :TODO: cache this.
    7.12      return ArrayType::New(zone_, contained, elements);
    7.13  }
    7.14  
    7.15 -Type *
    7.16 +ArrayType *
    7.17  TypeManager::newExternalArray(Handle<Type> contained)
    7.18  {
    7.19      return ArrayType::NewExternal(zone_, contained);
    7.20  }
    7.21  
    7.22 -Type *
    7.23 +ReferenceType *
    7.24  TypeManager::getReference(Handle<Type> type, bool isConst)
    7.25  {
    7.26      if (!isConst && type->isPrimitive())
    7.27 @@ -87,10 +87,10 @@
    7.28      return ReferenceType::New(zone_, type);
    7.29  }
    7.30  
    7.31 -Type *
    7.32 +EnumType *
    7.33  TypeManager::newEnum(Handle<String> name)
    7.34  {
    7.35 -    return Type::NewEnum(zone_, name);
    7.36 +    return EnumType::New(zone_, name);
    7.37  }
    7.38  
    7.39  void
     8.1 --- a/src/TypeManager.h	Sat Dec 22 19:48:43 2012 -0800
     8.2 +++ b/src/TypeManager.h	Sat Dec 22 23:18:57 2012 -0800
     8.3 @@ -35,7 +35,7 @@
     8.4      Unbarriered<Type> voidType_;
     8.5      Unbarriered<Type> uncheckedType_;
     8.6      Unbarriered<Type> primitiveTypes_[PrimitiveTypes_Total];
     8.7 -    Unbarriered<Type> referenceTypes_[PrimitiveTypes_Total];
     8.8 +    Unbarriered<ReferenceType> referenceTypes_[PrimitiveTypes_Total];
     8.9  
    8.10    public:
    8.11      TypeManager(Zone *zone);
    8.12 @@ -52,10 +52,10 @@
    8.13      Type *getUnchecked() {
    8.14          return uncheckedType_;
    8.15      }
    8.16 -    Type *getReference(Handle<Type> type, bool isConst);
    8.17 -    Type *newArray(Handle<Type> contained, int elements);
    8.18 -    Type *newExternalArray(Handle<Type> contained);
    8.19 -    Type *newEnum(Handle<String> name);
    8.20 +    ReferenceType *getReference(Handle<Type> type, bool isConst);
    8.21 +    ArrayType *newArray(Handle<Type> contained, int elements);
    8.22 +    ArrayType *newExternalArray(Handle<Type> contained);
    8.23 +    EnumType *newEnum(Handle<String> name);
    8.24      
    8.25      void accept(VirtualObjectVisitor *visitor);
    8.26  };
     9.1 --- a/src/Types.cpp	Sat Dec 22 19:48:43 2012 -0800
     9.2 +++ b/src/Types.cpp	Sat Dec 22 23:18:57 2012 -0800
     9.3 @@ -55,8 +55,7 @@
     9.4          return NULL;
     9.5  
     9.6      type->kind_ = PRIMITIVE;
     9.7 -    type->name_ = NULL;
     9.8 -     type->primitive_ = prim;
     9.9 +    type->primitive_ = prim;
    9.10      return type;
    9.11  }
    9.12  
    9.13 @@ -75,7 +74,6 @@
    9.14          return NULL;
    9.15  
    9.16      type->kind_ = ARRAY;
    9.17 -    type->name_ = NULL;
    9.18      type->contained_ = contained;
    9.19      type->elements_ = elements;
    9.20      if (!contained->isArray())
    9.21 @@ -95,7 +93,6 @@
    9.22      assert(contained->isPrimitive());
    9.23  
    9.24      type->kind_ = EXTERNAL_ARRAY;
    9.25 -    type->name_ = NULL;
    9.26      type->contained_ = contained;
    9.27      type->elements_ = DYNAMIC_ARRAY_SIZE;
    9.28      type->levels_ = 1;
    9.29 @@ -110,16 +107,15 @@
    9.30          return NULL;
    9.31  
    9.32      type->kind_ = REFERENCE;
    9.33 -    type->name_ = NULL;
    9.34      type->const_ = false;
    9.35      type->contained_ = contained;
    9.36      return type;
    9.37  }
    9.38  
    9.39 -Type *
    9.40 -Type::NewEnum(Zone *zone, Handle<String> name)
    9.41 +EnumType *
    9.42 +EnumType::New(Zone *zone, Handle<String> name)
    9.43  {
    9.44 -    Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    9.45 +    Local<EnumType> type(zone, EnumType::cast(zone->allocate(MapKind_EnumType, sizeof(EnumType), Heap::Tenure_Old)));
    9.46      if (!type)
    9.47          return NULL;
    9.48  
    9.49 @@ -138,7 +134,6 @@
    9.50          return NULL;
    9.51  
    9.52      type->kind_ = NATIVE;
    9.53 -    type->name_ = NULL;
    9.54      type->contained_ = NULL;
    9.55      type->fields_ = NULL;
    9.56      type->newMap_ = NULL;
    9.57 @@ -217,9 +212,9 @@
    9.58          return NULL;
    9.59  
    9.60      type->kind_ = STRUCT;
    9.61 -    type->name_ = name;
    9.62      type->newMap_ = NULL;
    9.63      type->fields_ = fields;
    9.64 +    type->name_ = name;
    9.65  
    9.66      // Fill in field offsets.
    9.67      StructureBufferBuilder builder;
    9.68 @@ -259,17 +254,17 @@
    9.69  }
    9.70  
    9.71  FunctionType *
    9.72 -FunctionType::New(Zone *zone, TokenKind token)
    9.73 +FunctionType::New(Zone *zone, Handle<String> name, TokenKind token)
    9.74  {
    9.75      Local<FunctionType> type(zone, FunctionType::cast(zone->allocate(MapKind_FunctionType, sizeof(FunctionType), Heap::Tenure_Old)));
    9.76      if (!type)
    9.77          return NULL;
    9.78  
    9.79      type->kind_ = FUNCTION;
    9.80 -    type->name_ = NULL;
    9.81      type->parameters_ = NULL;
    9.82      type->defaults_ = NULL;
    9.83      type->returnType_ = NULL;
    9.84 +    type->name_ = name;
    9.85      type->token_ = token;
    9.86      return type;
    9.87  }
    9.88 @@ -284,8 +279,10 @@
    9.89          return "function";
    9.90      if (type->isVoid())
    9.91          return "void";
    9.92 -    if (type->isEnum() || type->isStruct())
    9.93 -        return type->name()->chars();
    9.94 +    if (type->isEnum())
    9.95 +        return EnumType::cast(type)->name()->chars();
    9.96 +    if (type->isStruct())
    9.97 +        return StructType::cast(type)->name()->chars();
    9.98      if (type->isReference())
    9.99          type = ReferenceType::cast(type)->contained();
   9.100      switch (type->primitive()) {
    10.1 --- a/src/Types.h	Sat Dec 22 19:48:43 2012 -0800
    10.2 +++ b/src/Types.h	Sat Dec 22 23:18:57 2012 -0800
    10.3 @@ -104,7 +104,6 @@
    10.4      static Type *NewVoid(Zone *zone);
    10.5      static Type *NewUnchecked(Zone *zone);
    10.6      static Type *NewPrimitive(Zone *zone, PrimitiveType type);
    10.7 -    static Type *NewEnum(Zone *zone, Handle<String> name);
    10.8  
    10.9      static bool Compare(Type *left, Type *right);
   10.10  
   10.11 @@ -114,7 +113,8 @@
   10.12                 obj->is(MapKind_FunctionType) ||
   10.13                 obj->is(MapKind_StructType) ||
   10.14                 obj->is(MapKind_ArrayType) ||
   10.15 -               obj->is(MapKind_ReferenceType));
   10.16 +               obj->is(MapKind_ReferenceType) ||
   10.17 +               obj->is(MapKind_EnumType));
   10.18          return (Type *)obj;
   10.19      }
   10.20  
   10.21 @@ -185,25 +185,35 @@
   10.22          return kind() == ENUM;
   10.23      }
   10.24  
   10.25 -    String *name() {
   10.26 -        assert(isEnum() || isStruct());
   10.27 -        return name_;
   10.28 -    }
   10.29 -
   10.30 -    // GC Descriptor.
   10.31 -    static inline size_t offsetOfName() {
   10.32 -        return OFFSETOF(Type, name_);
   10.33 -    }
   10.34 -    // End GC Descriptor.
   10.35 -
   10.36    protected:
   10.37      Kind kind_;
   10.38      PrimitiveType primitive_;
   10.39  
   10.40      // Primitives, arrays, and references.
   10.41      bool const_;
   10.42 +};
   10.43  
   10.44 -    // Enums and structs only.
   10.45 +class EnumType : public Type
   10.46 +{
   10.47 +  public:
   10.48 +    static EnumType *New(Zone *Zone, Handle<String> name);
   10.49 +
   10.50 +    String *name() {
   10.51 +        return name_;
   10.52 +    }
   10.53 +
   10.54 +    // GC Descriptor.
   10.55 +    static inline size_t offsetOfName() {
   10.56 +        return OFFSETOF(EnumType, name_);
   10.57 +    }
   10.58 +    // End GC Descriptor.
   10.59 +
   10.60 +    static EnumType *cast(Object *obj) {
   10.61 +        assert(!obj || obj->is(MapKind_EnumType));
   10.62 +        return (EnumType *)obj;
   10.63 +    }
   10.64 +
   10.65 +  private:
   10.66      Barriered<String> name_;
   10.67  };
   10.68  
   10.69 @@ -325,6 +335,10 @@
   10.70          newMap_ = map;
   10.71      }
   10.72  
   10.73 +    String *name() {
   10.74 +        return name_;
   10.75 +    }
   10.76 +
   10.77      // GC Descriptor.
   10.78      static inline size_t offsetOfFields() {
   10.79          return OFFSETOF(StructType, fields_);
   10.80 @@ -332,6 +346,9 @@
   10.81      static inline size_t offsetOfNewMap() {
   10.82          return OFFSETOF(StructType, newMap_);
   10.83      }
   10.84 +    static inline size_t offsetOfName() {
   10.85 +        return OFFSETOF(StructType, name_);
   10.86 +    }
   10.87      // End GC Descriptor.
   10.88  
   10.89      static StructType *cast(Object *obj) {
   10.90 @@ -343,12 +360,13 @@
   10.91      // Structs only.
   10.92      Barriered<FixedArray> fields_;
   10.93      Barriered<StructMap> newMap_;
   10.94 +    Barriered<String> name_;
   10.95  };
   10.96  
   10.97  class FunctionType : public Type
   10.98  {
   10.99    public:
  10.100 -    static FunctionType *New(Zone *zone, TokenKind kind);
  10.101 +    static FunctionType *New(Zone *zone, Handle<String> name, TokenKind kind);
  10.102  
  10.103      Type *parameterAt(size_t i) {
  10.104          return Type::cast(parameters()->at(i));
  10.105 @@ -386,6 +404,9 @@
  10.106      TokenKind token() {
  10.107          return token_;
  10.108      }
  10.109 +    String *name() {
  10.110 +        return name_;
  10.111 +    }
  10.112  
  10.113      // GC Descriptor.
  10.114      static inline size_t offsetOfReturnType() {
  10.115 @@ -397,6 +418,9 @@
  10.116      static inline size_t offsetOfDefaults() {
  10.117          return OFFSETOF(FunctionType, defaults_);
  10.118      }
  10.119 +    static inline size_t offsetOfName() {
  10.120 +        return OFFSETOF(FunctionType, name_);
  10.121 +    }
  10.122      // End GC Descriptor.
  10.123  
  10.124      static FunctionType *cast(Object *obj) {
  10.125 @@ -409,6 +433,7 @@
  10.126      Barriered<Type> returnType_;
  10.127      Barriered<FixedArray> parameters_;
  10.128      Barriered<FixedArray> defaults_;
  10.129 +    Barriered<String> name_;
  10.130      TokenKind token_;
  10.131      bool variadicNative_;
  10.132  };
    11.1 --- a/src/Zone.cpp	Sat Dec 22 19:48:43 2012 -0800
    11.2 +++ b/src/Zone.cpp	Sat Dec 22 23:18:57 2012 -0800
    11.3 @@ -81,6 +81,7 @@
    11.4          MapKind_FunctionType,
    11.5          MapKind_StructType,
    11.6          MapKind_ReferenceType,
    11.7 +        MapKind_EnumType,
    11.8          MapKind_FixedArray,
    11.9          MapKind_ByteArray,
   11.10          MapKind_Code,
    12.1 --- a/src/compiler/AST.h	Sat Dec 22 19:48:43 2012 -0800
    12.2 +++ b/src/compiler/AST.h	Sat Dec 22 23:18:57 2012 -0800
    12.3 @@ -883,10 +883,12 @@
    12.4      struct Entry {
    12.5          ScopedRoot<String> name;
    12.6          Expression *expr;
    12.7 +        SourcePosition pos;
    12.8  
    12.9 -        Entry(Handle<String> name, Expression *expr)
   12.10 +        Entry(Handle<String> name, Expression *expr, const SourcePosition &pos)
   12.11            : name(name),
   12.12 -            expr(expr)
   12.13 +            expr(expr),
   12.14 +            pos(pos)
   12.15          {
   12.16          }
   12.17      };
    13.1 --- a/src/compiler/NameBinding.cpp	Sat Dec 22 19:48:43 2012 -0800
    13.2 +++ b/src/compiler/NameBinding.cpp	Sat Dec 22 23:18:57 2012 -0800
    13.3 @@ -198,13 +198,52 @@
    13.4              node->initialization()->accept(this);
    13.5      }
    13.6      void visitEnumStatement(EnumStatement *node) {
    13.7 -        assert(false);
    13.8 +        Local<String> name(zone_, node->name());
    13.9 +        Local<Type> type(zone_);
   13.10 +        if (name)
   13.11 +            type = zone_->types()->newEnum(name);
   13.12 +        else
   13.13 +            type = zone_->types()->getPrimitive(PrimitiveType_Int32);
   13.14 +
   13.15 +        if (!type)
   13.16 +            return;
   13.17 +
   13.18 +        Scope *scope = getGlobalOrCreateBlockScope();
   13.19 +        if (!scope)
   13.20 +            return;
   13.21 +
   13.22 +        if (name) {
   13.23 +            TypeSymbol *sym = new (pool_) TypeSymbol(scope, name, type);
   13.24 +            if (!registerName(scope, sym))
   13.25 +                return;
   13.26 +        }
   13.27 +
   13.28 +        int value = 0;
   13.29 +        for (size_t i = 0; i < node->entries()->length(); i++) {
   13.30 +            EnumStatement::Entry &entry = node->entries()->at(i);
   13.31 +            BoxedPrimitive box = BoxedPrimitive::Int(value);
   13.32 +            if (entry.expr) {
   13.33 +                if (!EvaluateForConstant(entry.expr, &box) || box.type() != PrimitiveType_Int32) {
   13.34 +                    cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
   13.35 +                    return;
   13.36 +                }
   13.37 +
   13.38 +                assert(box.type() == PrimitiveType_Int32);
   13.39 +                value = box.toInt();
   13.40 +            }
   13.41 +            
   13.42 +            ConstantSymbol *sym = new (pool_) ConstantSymbol(scope, entry.name, entry.pos, type, box);
   13.43 +            if (!registerName(scope, sym))
   13.44 +                return;
   13.45 +
   13.46 +            value++;
   13.47 +        }
   13.48      }
   13.49      void visitFunctionStatement(FunctionStatement *node) {
   13.50          // We create function types ahead of time, not for any particular
   13.51          // reason. It makes things consistent with FunctionTypeStatement,
   13.52          // which actually does produce a type.
   13.53 -        Local<FunctionType> type(zone_, FunctionType::New(zone_, node->token()));
   13.54 +        Local<FunctionType> type(zone_, FunctionType::New(zone_, node->name(), node->token()));
   13.55          if (!type)
   13.56              return;
   13.57  
   13.58 @@ -360,6 +399,14 @@
   13.59      }
   13.60  
   13.61    private:
   13.62 +    Scope *getGlobalOrCreateBlockScope() {
   13.63 +        if (env_->scope()) {
   13.64 +            assert(env_->scope()->kind() == Scope::BLOCK ||
   13.65 +                   env_->scope()->kind() == Scope::GLOBAL);
   13.66 +            return env_->scope();
   13.67 +        }
   13.68 +        return getOrCreateBlockScope();
   13.69 +    }
   13.70      Scope *getOrCreateBlockScope() {
   13.71          if (env_->scope()) {
   13.72              assert(env_->scope()->kind() == Scope::BLOCK);
   13.73 @@ -546,11 +593,9 @@
   13.74              return;
   13.75          }
   13.76          
   13.77 -        if (link_->scope()->addSymbol(sym))
   13.78 -            return;
   13.79 +        link_->scope()->addSymbol(sym);
   13.80      }
   13.81      void visitEnumStatement(EnumStatement *node) {
   13.82 -        assert(false);
   13.83      }
   13.84      void visitFunctionStatement(FunctionStatement *node) {
   13.85          AutoLinkScope argScope(&link_, node->argScope());
    14.1 --- a/src/compiler/Parser.cpp	Sat Dec 22 19:48:43 2012 -0800
    14.2 +++ b/src/compiler/Parser.cpp	Sat Dec 22 23:18:57 2012 -0800
    14.3 @@ -1180,6 +1180,7 @@
    14.4          if (scanner_.peek() == TOK_RBRACE)
    14.5              break;
    14.6  
    14.7 +        SourcePosition &pos = scanner_.begin();
    14.8          Local<String> name(zone_, expectName());
    14.9          if (!name)
   14.10              return NULL;
   14.11 @@ -1190,7 +1191,7 @@
   14.12                  return NULL;
   14.13          }
   14.14  
   14.15 -        if (!entries->append(EnumStatement::Entry(name, expr)))
   14.16 +        if (!entries->append(EnumStatement::Entry(name, expr, pos)))
   14.17              return NULL;
   14.18      } while (match(TOK_COMMA));
   14.19      if (!expect(TOK_RBRACE))
    15.1 --- a/src/compiler/SemanticAnalysis.cpp	Sat Dec 22 19:48:43 2012 -0800
    15.2 +++ b/src/compiler/SemanticAnalysis.cpp	Sat Dec 22 23:18:57 2012 -0800
    15.3 @@ -214,6 +214,11 @@
    15.4  }
    15.5  
    15.6  void
    15.7 +SemanticAnalysis::visitEnumStatement(EnumStatement *node)
    15.8 +{
    15.9 +}
   15.10 +
   15.11 +void
   15.12  SemanticAnalysis::visitExpressionStatement(ExpressionStatement *node)
   15.13  {
   15.14      // While building HIR, we enter new pool and root scopes, since HIR
   15.15 @@ -545,24 +550,51 @@
   15.16  SemanticAnalysis::visitNameProxy(NameProxy *proxy)
   15.17  {
   15.18      Symbol *sym = proxy->sym();
   15.19 -    VariableSymbol *var = sym->asVariable();
   15.20  
   15.21 -    Scope *in = sym->scope();
   15.22 -    switch (in->kind()) {
   15.23 -      case Scope::GLOBAL:
   15.24 -        hir_ = new (pool_) HGlobal(proxy, sym);
   15.25 -        return;
   15.26 +    switch (sym->kind()) {
   15.27 +      case Symbol::kConstant:
   15.28 +      {
   15.29 +        ConstantSymbol *val = sym->toConstant();
   15.30 +        hir_ = new (pool_) HInteger(proxy, sym->type(), val->value().toInt());
   15.31 +        break;
   15.32 +      }
   15.33 +      
   15.34 +      // This is kind of screwy. Symbol::kFunction is like a constant we can't
   15.35 +      // evaluate yet. Maybe we should extract the GLOBAL case and say that
   15.36 +      // kFunction is only used for global functions (and use const vars for
   15.37 +      // local functions).
   15.38 +      case Symbol::kFunction:
   15.39 +      case Symbol::kVariable:
   15.40 +      {
   15.41 +        Scope *in = sym->scope();
   15.42 +        switch (in->kind()) {
   15.43 +          case Scope::GLOBAL:
   15.44 +            hir_ = new (pool_) HGlobal(proxy, sym);
   15.45 +            break;
   15.46  
   15.47 -      case Scope::FUNCTION:
   15.48 -        assert(var->storage() == VariableSymbol::Arg);
   15.49 -        hir_ = new (pool_) HLocal(proxy, var);
   15.50 -        return;
   15.51 +          case Scope::FUNCTION:
   15.52 +          {
   15.53 +            VariableSymbol *var = sym->toVariable();
   15.54 +            assert(var->storage() == VariableSymbol::Arg);
   15.55 +            hir_ = new (pool_) HLocal(proxy, var);
   15.56 +            break;
   15.57 +          }
   15.58 +
   15.59 +          default:
   15.60 +          {
   15.61 +            VariableSymbol *var = sym->toVariable();
   15.62 +            assert(in->kind() == Scope::BLOCK);
   15.63 +            assert(var->storage() == VariableSymbol::Local);
   15.64 +            hir_ = new (pool_) HLocal(proxy, var);
   15.65 +            break;
   15.66 +          }
   15.67 +        }
   15.68 +        break;
   15.69 +      }
   15.70  
   15.71        default:
   15.72 -        assert(in->kind() == Scope::BLOCK);
   15.73 -        assert(var->storage() == VariableSymbol::Local);
   15.74 -        hir_ = new (pool_) HLocal(proxy, var);
   15.75 -        return;
   15.76 +        // :TODO:
   15.77 +        assert(false);
   15.78      }
   15.79  }
   15.80  
   15.81 @@ -854,6 +886,15 @@
   15.82  }
   15.83  
   15.84  HIR *
   15.85 +SemanticAnalysis::typeFailure(const SourcePosition &pos, Handle<Type> from, Handle<Type> to)
   15.86 +{
   15.87 +    cc_.reportError(pos, Message_InvalidCoercion,
   15.88 +                    GetTypeName(from),
   15.89 +                    GetTypeName(to));
   15.90 +    return NULL;
   15.91 +}
   15.92 +
   15.93 +HIR *
   15.94  SemanticAnalysis::coerce(HIR *hir, Handle<Type> to, CoercionKind kind)
   15.95  {
   15.96      Handle<Type> from = hir->type();
   15.97 @@ -862,6 +903,9 @@
   15.98          return new (pool_) HConvert(hir->node(), to, OP_CVT_I2F, hir);
   15.99      if (from->isInt32() && to->isBool())
  15.100          return new (pool_) HConvert(hir->node(), to, OP_CVT_I2B, hir);
  15.101 +
  15.102 +    if (to->isEnum() && from != to)
  15.103 +        return typeFailure(hir->node()->pos(), from, to);
  15.104      
  15.105      if (to->isArray()) {
  15.106          if (!typeCheckArray(SourcePosition(), from, to, kind))
    16.1 --- a/src/compiler/SemanticAnalysis.h	Sat Dec 22 19:48:43 2012 -0800
    16.2 +++ b/src/compiler/SemanticAnalysis.h	Sat Dec 22 23:18:57 2012 -0800
    16.3 @@ -48,6 +48,7 @@
    16.4      void visitBlockStatement(BlockStatement *node);
    16.5      void visitExpressionStatement(ExpressionStatement *node);
    16.6      void visitReturnStatement(ReturnStatement *node);
    16.7 +    void visitEnumStatement(EnumStatement *node);
    16.8  
    16.9      void visitCallExpression(CallExpression *node);
   16.10      void visitNameProxy(NameProxy *name);
   16.11 @@ -66,7 +67,6 @@
   16.12  #if 0
   16.13      void visitFunctionTypeStatement(FunctionTypeStatement *node);
   16.14      void visitImportStatement(ImportStatement *node);
   16.15 -    void visitEnumStatement(EnumStatement *node);
   16.16      void visitStructureStatement(StructureStatement *node);
   16.17      void visitSwitchStatement(SwitchStatement *node);
   16.18  
   16.19 @@ -178,6 +178,7 @@
   16.20      Type *coercionType(TokenKind token, HIR *left, HIR *right);
   16.21      HLValue *lvalue(Expression *expr);
   16.22      void discharge(HIR *hir);
   16.23 +    HIR *typeFailure(const SourcePosition &pos, Handle<Type> from, Handle<Type> to);
   16.24  
   16.25      bool typeCheckArray(const SourcePosition &pos,
   16.26                          Handle<Type> argGiven,
    17.1 --- a/src/compiler/Symbols.h	Sat Dec 22 19:48:43 2012 -0800
    17.2 +++ b/src/compiler/Symbols.h	Sat Dec 22 23:18:57 2012 -0800
    17.3 @@ -186,6 +186,28 @@
    17.4      }
    17.5  };
    17.6  
    17.7 +class ConstantSymbol : public Symbol
    17.8 +{
    17.9 +  public:
   17.10 +    ConstantSymbol(Scope *scope, Handle<String> name, const SourcePosition &pos, Handle<Type> type,
   17.11 +                   const BoxedPrimitive &prim)
   17.12 +      : Symbol(scope, name, pos),
   17.13 +        value_(prim)
   17.14 +    {
   17.15 +        type_ = type;
   17.16 +    }
   17.17 +
   17.18 +    Kind kind() const {
   17.19 +        return kConstant;
   17.20 +    }
   17.21 +    const BoxedPrimitive &value() const {
   17.22 +        return value_;
   17.23 +    }
   17.24 +
   17.25 +  private:
   17.26 +    BoxedPrimitive value_;
   17.27 +};
   17.28 +
   17.29  }
   17.30  
   17.31  #endif // _include_sp2_symbol_h_
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/tests/basic/enum-bad.err	Sat Dec 22 23:18:57 2012 -0800
    18.3 @@ -0,0 +1,1 @@
    18.4 +  line 6, col 13: cannot coerce type 'int' to type 'X'
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/tests/basic/enum-bad.sp	Sat Dec 22 23:18:57 2012 -0800
    19.3 @@ -0,0 +1,7 @@
    19.4 +enum X {
    19.5 +};
    19.6 +
    19.7 +public main()
    19.8 +{
    19.9 +    new X:x = 5;
   19.10 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/tests/basic/enum-redecl.err	Sat Dec 22 23:18:57 2012 -0800
    20.3 @@ -0,0 +1,1 @@
    20.4 +  line 4, col 4: name 'Y' was redeclared (previous at line 2, col 4)
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/tests/basic/enum-redecl.sp	Sat Dec 22 23:18:57 2012 -0800
    21.3 @@ -0,0 +1,6 @@
    21.4 +enum X {
    21.5 +  Y,
    21.6 +  Z,
    21.7 +  Y
    21.8 +};
    21.9 +
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/tests/basic/enum-use.out	Sat Dec 22 23:18:57 2012 -0800
    22.3 @@ -0,0 +1,1 @@
    22.4 +01570157
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/tests/basic/enum-use.sp	Sat Dec 22 23:18:57 2012 -0800
    23.3 @@ -0,0 +1,28 @@
    23.4 +native PrintNum(num);
    23.5 +
    23.6 +enum Crab {
    23.7 +   CrabOne,
    23.8 +   CrabTwo,
    23.9 +   CrabThree=5,
   23.10 +   CrabFour=7
   23.11 +};
   23.12 +
   23.13 +enum {
   23.14 +   CrabFive,
   23.15 +   CrabSix,
   23.16 +   CrabSeven=5,
   23.17 +   CrabEight=7
   23.18 +};
   23.19 +
   23.20 +public main()
   23.21 +{
   23.22 +   PrintNum(CrabOne);
   23.23 +   PrintNum(CrabTwo);
   23.24 +   PrintNum(CrabThree);
   23.25 +   PrintNum(CrabFour);
   23.26 +   PrintNum(CrabFive);
   23.27 +   PrintNum(CrabSix);
   23.28 +   PrintNum(CrabSeven);
   23.29 +   PrintNum(CrabEight);
   23.30 +}
   23.31 +