Add support for importing enum types and enum values (as constexprs).
authorDavid Anderson <dvander@alliedmods.net>
Sun Jan 27 17:34:30 2013 -0800 (2013-01-27)
changeset 261219b49bf4a03
parent 260 05de34f712fe
child 262 c4b1341297e5
Add support for importing enum types and enum values (as constexprs).
src/ObjectVisitor.h
src/RootScopes.h
src/TypeManager.cpp
src/TypeManager.h
src/Types.cpp
src/Types.h
src/compiler/AST.h
src/compiler/CompileContext.h
src/compiler/NameBinding.cpp
src/compiler/Parser.cpp
src/compiler/Parser.h
src/compiler/SemanticAnalysis.cpp
src/compiler/Symbols.h
tests/basic/import_enum_a.out
tests/basic/import_enum_a.sp
tests/basic/import_enum_b.sp
     1.1 --- a/src/ObjectVisitor.h	Sat Jan 12 16:35:26 2013 -0800
     1.2 +++ b/src/ObjectVisitor.h	Sun Jan 27 17:34:30 2013 -0800
     1.3 @@ -54,6 +54,7 @@
     1.4  
     1.5      size_t iterateEnumType(Object *obj) {
     1.6          visitField(obj, EnumType::offsetOfName());
     1.7 +        visitField(obj, EnumType::offsetOfFields());
     1.8          return sizeof(EnumType);
     1.9      }
    1.10  
     2.1 --- a/src/RootScopes.h	Sat Jan 12 16:35:26 2013 -0800
     2.2 +++ b/src/RootScopes.h	Sun Jan 27 17:34:30 2013 -0800
     2.3 @@ -2,19 +2,19 @@
     2.4   *
     2.5   * Copyright (C) 2012 David Anderson
     2.6   *
     2.7 - * This file is part of JITCraft.
     2.8 + * This file is part of SourcePawn.
     2.9   *
    2.10 - * JITCraft is free software: you can redistribute it and/or modify it under
    2.11 + * SourcePawn is free software: you can redistribute it and/or modify it under
    2.12   * the terms of the GNU General Public License as published by the Free
    2.13   * Software Foundation, either version 3 of the License, or (at your option)
    2.14   * any later version.
    2.15   * 
    2.16 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    2.17 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    2.18   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    2.19   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    2.20   *
    2.21   * You should have received a copy of the GNU General Public License along with
    2.22 - * JITCraft. If not, see http://www.gnu.org/licenses/.
    2.23 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
    2.24   */
    2.25  #ifndef _include_jc_root_scopes_h_
    2.26  #define _include_jc_root_scopes_h_
     3.1 --- a/src/TypeManager.cpp	Sat Jan 12 16:35:26 2013 -0800
     3.2 +++ b/src/TypeManager.cpp	Sun Jan 27 17:34:30 2013 -0800
     3.3 @@ -52,6 +52,10 @@
     3.4      if (!importableType_)
     3.5          return false;
     3.6  
     3.7 +    typeType_ = Type::NewType(zone_);
     3.8 +    if (!typeType_)
     3.9 +        return false;
    3.10 +
    3.11      if ((primitiveTypes_[PrimitiveType_Int32] = Type::NewPrimitive(zone_, PrimitiveType_Int32)) == NULL)
    3.12          return false;
    3.13      if ((primitiveTypes_[PrimitiveType_Float] = Type::NewPrimitive(zone_, PrimitiveType_Float)) == NULL)
    3.14 @@ -141,6 +145,7 @@
    3.15      visitor->visit(uncheckedType_.address());
    3.16      visitor->visit(stringType_.address());
    3.17      visitor->visit(importableType_.address());
    3.18 +    visitor->visit(typeType_.address());
    3.19      for (unsigned i = 0; i < PrimitiveTypes_Total; i++) {
    3.20          visitor->visit(primitiveTypes_[i].address());
    3.21          visitor->visit(referenceTypes_[i].address());
     4.1 --- a/src/TypeManager.h	Sat Jan 12 16:35:26 2013 -0800
     4.2 +++ b/src/TypeManager.h	Sun Jan 27 17:34:30 2013 -0800
     4.3 @@ -82,6 +82,9 @@
     4.4      Type *getImportable() {
     4.5          return importableType_;
     4.6      }
     4.7 +    Type *getType() {
     4.8 +        return typeType_;
     4.9 +    }
    4.10      ReferenceType *getReference(Handle<Type> type, bool isConst);
    4.11      ArrayType *newArray(Handle<Type> contained, int elements);
    4.12      ArrayType *newExternalArray(Handle<Type> contained);
    4.13 @@ -100,6 +103,7 @@
    4.14      Unbarriered<Type> stringType_;
    4.15      Unbarriered<Type> uncheckedType_;
    4.16      Unbarriered<Type> importableType_;
    4.17 +    Unbarriered<Type> typeType_;
    4.18      Unbarriered<Type> primitiveTypes_[PrimitiveTypes_Total];
    4.19      Unbarriered<ReferenceType> referenceTypes_[PrimitiveTypes_Total];
    4.20  
     5.1 --- a/src/Types.cpp	Sat Jan 12 16:35:26 2013 -0800
     5.2 +++ b/src/Types.cpp	Sun Jan 27 17:34:30 2013 -0800
     5.3 @@ -78,6 +78,17 @@
     5.4  }
     5.5  
     5.6  Type *
     5.7 +Type::NewType(Zone *zone)
     5.8 +{
     5.9 +    Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    5.10 +    if (!type)
    5.11 +        return NULL;
    5.12 +
    5.13 +    type->init(TYPE);
    5.14 +    return type;
    5.15 +}
    5.16 +
    5.17 +Type *
    5.18  Type::NewPrimitive(Zone *zone, PrimitiveType prim)
    5.19  {
    5.20      Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
    5.21 @@ -167,6 +178,7 @@
    5.22  
    5.23      type->init(ENUM);
    5.24      type->name_ = name;
    5.25 +    type->fields_ = NULL;
    5.26      return type;
    5.27  }
    5.28  
     6.1 --- a/src/Types.h	Sat Jan 12 16:35:26 2013 -0800
     6.2 +++ b/src/Types.h	Sun Jan 27 17:34:30 2013 -0800
     6.3 @@ -65,7 +65,11 @@
     6.4      TypeQual_None           = 0,
     6.5  
     6.6      // Values of this type cannot be modified.
     6.7 -    TypeQual_Const       = (1 << 2)
     6.8 +    TypeQual_Const       = (1 << 0),
     6.9 +
    6.10 +    // Values of this type can be treated as constant expressions. This allows
    6.11 +    // us to export compile-time constants from modules.
    6.12 +    TypeQual_ConstExpr   = (1 << 1)
    6.13  };
    6.14  
    6.15  class Type : public Object
    6.16 @@ -115,7 +119,10 @@
    6.17  
    6.18          // Importable types are mainly used during the compilation process
    6.19          // to distinguish between normal names and static imports.
    6.20 -        IMPORTABLE
    6.21 +        IMPORTABLE,
    6.22 +
    6.23 +        // The type of types.
    6.24 +        TYPE
    6.25      };
    6.26  
    6.27      void init(Kind kind, Type *root = NULL);
    6.28 @@ -128,6 +135,7 @@
    6.29    public:   
    6.30      static Type *NewVoid(Zone *zone);
    6.31      static Type *NewUnchecked(Zone *zone);
    6.32 +    static Type *NewType(Zone *zone);
    6.33      static Type *NewPrimitive(Zone *zone, PrimitiveType type);
    6.34      static Type *NewString(Zone *zone);
    6.35      static Type *NewQualified(Zone *zone, TypeQualifiers qual, Handle<Type> type);
    6.36 @@ -210,6 +218,9 @@
    6.37      bool isEnum() {
    6.38          return kind() == ENUM;
    6.39      }
    6.40 +    bool isType() {
    6.41 +        return kind() == TYPE;
    6.42 +    }
    6.43      bool hasTypeQualifiers() {
    6.44          return kind_ == QUALTYPE;
    6.45      }
    6.46 @@ -252,6 +263,9 @@
    6.47      static inline size_t offsetOfName() {
    6.48          return OFFSETOF(EnumType, name_);
    6.49      }
    6.50 +    static inline size_t offsetOfFields() {
    6.51 +        return OFFSETOF(EnumType, fields_);
    6.52 +    }
    6.53      // End GC Descriptor.
    6.54  
    6.55      static EnumType *cast(Object *obj) {
    6.56 @@ -261,6 +275,7 @@
    6.57  
    6.58    private:
    6.59      Barriered<String> name_;
    6.60 +    Barriered<FixedArray> fields_;
    6.61  };
    6.62  
    6.63  class ReferenceType : public Type
     7.1 --- a/src/compiler/AST.h	Sat Jan 12 16:35:26 2013 -0800
     7.2 +++ b/src/compiler/AST.h	Sun Jan 27 17:34:30 2013 -0800
     7.3 @@ -873,11 +873,13 @@
     7.4          ScopedRoot<String> name;
     7.5          Expression *expr;
     7.6          SourcePosition pos;
     7.7 +        ConstantSymbol *sym;
     7.8  
     7.9          Entry(Handle<String> name, Expression *expr, const SourcePosition &pos)
    7.10            : name(name),
    7.11              expr(expr),
    7.12 -            pos(pos)
    7.13 +            pos(pos),
    7.14 +            sym(NULL)
    7.15          {
    7.16          }
    7.17      };
    7.18 @@ -885,17 +887,18 @@
    7.19      typedef PoolList<Entry> EntryList;
    7.20  
    7.21    public:
    7.22 -    EnumStatement(const SourcePosition &pos, Handle<String> name, EntryList *entries)
    7.23 +    EnumStatement(const SourcePosition &pos, TokenKind visibility, Handle<String> name, EntryList *entries)
    7.24        : Statement(pos),
    7.25          name_(name),
    7.26          sym_(NULL),
    7.27 -        entries_(entries)
    7.28 +        entries_(entries),
    7.29 +        visibility_(visibility)
    7.30      {
    7.31      }
    7.32  
    7.33      DECLARE_NODE(EnumStatement);
    7.34  
    7.35 -    String *name() const {
    7.36 +    Handle<String> name() const {
    7.37          return name_;
    7.38      }
    7.39      EntryList *entries() const {
    7.40 @@ -908,9 +911,13 @@
    7.41      TypeSymbol *sym() const {
    7.42          return sym_;
    7.43      }
    7.44 +    TokenKind visibility() const {
    7.45 +        return visibility_;
    7.46 +    }
    7.47  
    7.48    private:
    7.49      EntryList *entries_;
    7.50 +    TokenKind visibility_;
    7.51  };
    7.52  
    7.53  class IncDecExpression : public Expression
     8.1 --- a/src/compiler/CompileContext.h	Sat Jan 12 16:35:26 2013 -0800
     8.2 +++ b/src/compiler/CompileContext.h	Sun Jan 27 17:34:30 2013 -0800
     8.3 @@ -62,7 +62,7 @@
     8.4          importScope_(NULL),
     8.5          globalScope_(NULL),
     8.6          module_(module),
     8.7 -        oom_(false),
     8.8 +        enoughMemory_(true),
     8.9          dependencyFailed_(false)
    8.10      {
    8.11      }
    8.12 @@ -83,7 +83,7 @@
    8.13      }
    8.14      bool failed() const {
    8.15          return errors_.length() ||
    8.16 -               oom_ ||
    8.17 +               !enoughMemory_ ||
    8.18                 dependencyFailed_;
    8.19      }
    8.20      void setImportScope(ImportScope *scope) {
    8.21 @@ -108,17 +108,17 @@
    8.22          dependencyFailed_ = true;
    8.23      }
    8.24      void setOutOfMemory() {
    8.25 -        oom_ = true;
    8.26 +        enoughMemory_ = false;
    8.27      }
    8.28      void appendError(const char *report, unsigned line, unsigned col) {
    8.29 -        oom_ |= errors_.append(CompileError(line, col, report));
    8.30 +        enoughMemory_ |= errors_.append(CompileError(line, col, report));
    8.31      }
    8.32      const Vector<CompileError> *errors() {
    8.33          return &errors_;
    8.34      }
    8.35  
    8.36    private:
    8.37 -    bool oom_;
    8.38 +    bool enoughMemory_;
    8.39      bool dependencyFailed_;
    8.40      Vector<CompileError> errors_;
    8.41  };
     9.1 --- a/src/compiler/NameBinding.cpp	Sat Jan 12 16:35:26 2013 -0800
     9.2 +++ b/src/compiler/NameBinding.cpp	Sun Jan 27 17:34:30 2013 -0800
     9.3 @@ -137,12 +137,14 @@
     9.4          return;
     9.5      }
     9.6  
     9.7 -    bool declareSystemType(ImportScope *scope, const char *name, Handle<Type> type) {
     9.8 +    bool declareSystemType(ImportScope *scope, const char *name, Handle<Type> effective) {
     9.9          Local<String> tag(zone_, zone_->makeSymbol(name));
    9.10          if (!tag)
    9.11              return false;
    9.12  
    9.13 -        TypeSymbol *sym = new (pool_) TypeSymbol(scope, tag, type);
    9.14 +        Local<Type> type(zone_, zone_->types()->getType());
    9.15 +
    9.16 +        TypeSymbol *sym = new (pool_) TypeSymbol(scope, tag, type, effective);
    9.17          return scope->addSymbol(sym);
    9.18      }
    9.19  
    9.20 @@ -214,7 +216,8 @@
    9.21              return;
    9.22  
    9.23          if (name) {
    9.24 -            TypeSymbol *sym = new (pool_) TypeSymbol(scope, name, type);
    9.25 +            Local<Type> symType(zone_, zone_->types()->getType());
    9.26 +            TypeSymbol *sym = new (pool_) TypeSymbol(scope, name, symType, type);
    9.27              if (!registerName(scope, sym))
    9.28                  return;
    9.29  
    9.30 @@ -224,6 +227,10 @@
    9.31              }
    9.32          }
    9.33  
    9.34 +        // We want each field of the expression to qualify as a constant expression.
    9.35 +        if ((type = zone_->types()->qualify(type, TypeQual_ConstExpr)) == NULL)
    9.36 +            return;
    9.37 +        
    9.38          int value = 0;
    9.39          for (size_t i = 0; i < node->entries()->length(); i++) {
    9.40              EnumStatement::Entry &entry = node->entries()->at(i);
    9.41 @@ -237,7 +244,7 @@
    9.42                  assert(box.type() == PrimitiveType_Int32);
    9.43                  value = box.toInt();
    9.44              }
    9.45 -            
    9.46 +         
    9.47              ConstantSymbol *sym = new (pool_) ConstantSymbol(scope, entry.name, entry.pos, type, box);
    9.48              if (!registerName(scope, sym))
    9.49                  return;
    9.50 @@ -246,6 +253,7 @@
    9.51                      return;
    9.52              }
    9.53  
    9.54 +            entry.sym = sym;
    9.55              value++;
    9.56          }
    9.57      }
    9.58 @@ -756,7 +764,7 @@
    9.59                  return NULL;
    9.60              }
    9.61  
    9.62 -            type = sym->type();
    9.63 +            type = sym->toType()->effective();
    9.64          }
    9.65  
    9.66          return zone_->types()->qualify(type, quals);
    9.67 @@ -771,6 +779,18 @@
    9.68  
    9.69  class GlobalBuilder : public NameBinderBase
    9.70  {
    9.71 +    typedef ScopedRoot<Descriptor> ScopedDescriptor;
    9.72 +    struct PrimitiveFill {
    9.73 +        ScopedDescriptor *desc;
    9.74 +        BoxedPrimitive prim;
    9.75 +
    9.76 +        PrimitiveFill(ScopedDescriptor *desc, BoxedPrimitive prim)
    9.77 +          : desc(desc),
    9.78 +            prim(prim)
    9.79 +        {
    9.80 +        }
    9.81 +    };
    9.82 +
    9.83    public:
    9.84      GlobalBuilder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
    9.85        : NameBinderBase(zone, cc, unit),
    9.86 @@ -788,6 +808,17 @@
    9.87              stmt->accept(this);
    9.88          }
    9.89  
    9.90 +        Local<Struct> globals(zone_, createGlobals());
    9.91 +        if (!globals)
    9.92 +            return NULL;
    9.93 +
    9.94 +        populate(globals);
    9.95 +
    9.96 +        return globals;
    9.97 +    }
    9.98 +
    9.99 +  private:
   9.100 +    Struct *createGlobals() {
   9.101          Local<FixedArray> descs(zone_, FixedArray::New(zone_, descriptors_.length(), Heap::Tenure_Old));
   9.102          if (!descs)
   9.103              return NULL;
   9.104 @@ -804,7 +835,47 @@
   9.105          return Struct::New(zone_, map, Heap::Tenure_Old);
   9.106      }
   9.107  
   9.108 +    void populate(Handle<Struct> globals) {
   9.109 +        // This is a huge hack, but it's probably better than a full extra
   9.110 +        // pass. The problem is that until we have all the descriptors, we
   9.111 +        // can't start setting constexprs in the struct, and we need to set
   9.112 +        // them now so they're available during full semantic analysis. To
   9.113 +        // work around this, we build up the list of values we need to set
   9.114 +        // as we build up descriptors, and then populate the global struct
   9.115 +        // with this set.
   9.116 +        //
   9.117 +        // Note, this code is also kind of dead until we support linking. We
   9.118 +        // handle constexprs explicitly in importFrom(), by sniffing out the
   9.119 +        // symbol type. That code will go away later.
   9.120 +        for (size_t i = 0; i < primitiveFills_.length(); i++) {
   9.121 +            const PrimitiveFill &fill = primitiveFills_[i];
   9.122 +            assert(fill.prim.type() == PrimitiveType_Int32);
   9.123 +            globals->set(*fill.desc, fill.prim.toInt());
   9.124 +        }
   9.125 +    }
   9.126 +
   9.127 +  public:
   9.128      void visitEnumStatement(EnumStatement *stmt) {
   9.129 +        if (stmt->visibility() != TOK_PUBLIC || !stmt->name())
   9.130 +            return;
   9.131 +
   9.132 +        Local<Type> type(zone_, zone_->types()->getType());
   9.133 +        Descriptor *desc = Descriptor::New(zone_, stmt->name(), type, Descriptor::Public);
   9.134 +        if (!desc)
   9.135 +            return;
   9.136 +        if (!descriptors_.append(new (pool_) ScopedRoot<Descriptor>(desc)))
   9.137 +            return;
   9.138 +
   9.139 +        for (size_t i = 0; i < stmt->entries()->length(); i++) {
   9.140 +            EnumStatement::Entry &e = stmt->entries()->at(i);
   9.141 +            ScopedDescriptor *desc = new (pool_) ScopedDescriptor(Descriptor::New(zone_, e.name, e.sym->type(), Descriptor::Public));
   9.142 +            if (!desc || !descriptors_.append(desc))
   9.143 +                return;
   9.144 +
   9.145 +            // Save the value so we can export it immediately.
   9.146 +            if (!primitiveFills_.append(PrimitiveFill(desc, e.sym->value())))
   9.147 +                return;
   9.148 +        }
   9.149      }
   9.150  
   9.151      void visitNameProxy(NameProxy *proxy) {
   9.152 @@ -917,11 +988,33 @@
   9.153              return false;
   9.154          }
   9.155  
   9.156 -        ImplicitSymbol *sym = new (pool_) ImplicitSymbol(unit_->importScope(),
   9.157 -                                                        import->name(),
   9.158 -                                                        node->pos(),
   9.159 -                                                        import->type(),
   9.160 -                                                        node->importIndex());
   9.161 +        Symbol *sym;
   9.162 +        if (import->isType()) {
   9.163 +            // Fuck it, make a TypeSymbol instead of an ImplicitSymbol. This
   9.164 +            // makes bindType() much simpler. We may run into problems
   9.165 +            // implementing linking, but it seems unlikely, as long as we are
   9.166 +            // exporting Types in module structs.
   9.167 +            Local<Type> type(zone_, zone_->types()->getType());
   9.168 +            sym = new (pool_) TypeSymbol(unit_->importScope(),
   9.169 +                                         import->name(),
   9.170 +                                         type,
   9.171 +                                         import->toType()->effective());
   9.172 +        } else if (import->isConstant()) {
   9.173 +            // Same deal. No reason to lookup in the module globals if we
   9.174 +            // already have a symbol.
   9.175 +            sym = new (pool_) ConstantSymbol(unit_->importScope(),
   9.176 +                                             import->name(),
   9.177 +                                             node->pos(),
   9.178 +                                             import->type(),
   9.179 +                                             import->toConstant()->value());
   9.180 +        } else {
   9.181 +            sym = new (pool_) ImplicitSymbol(unit_->importScope(),
   9.182 +                                             import->name(),
   9.183 +                                             node->pos(),
   9.184 +                                             import->type(),
   9.185 +                                             node->importIndex());
   9.186 +        }
   9.187 +
   9.188          if (!unit_->importScope()->addSymbol(sym))
   9.189              return false;
   9.190  
   9.191 @@ -963,6 +1056,7 @@
   9.192      StructureBufferBuilder builder_;
   9.193      Vector<ScopedRoot<Descriptor> *> descriptors_;
   9.194      GlobalScope *globalScope_;
   9.195 +    Vector<PrimitiveFill> primitiveFills_;
   9.196  };
   9.197      
   9.198  class NameBinder : public NameBinderBase
    10.1 --- a/src/compiler/Parser.cpp	Sat Jan 12 16:35:26 2013 -0800
    10.2 +++ b/src/compiler/Parser.cpp	Sun Jan 27 17:34:30 2013 -0800
    10.3 @@ -1106,7 +1106,7 @@
    10.4          break;
    10.5  
    10.6        case TOK_ENUM:
    10.7 -        if ((statement = enum_()) == NULL)
    10.8 +        if ((statement = enum_(TOK_NONE)) == NULL)
    10.9            return NULL;
   10.10          break;
   10.11  
   10.12 @@ -1189,7 +1189,7 @@
   10.13  }
   10.14  
   10.15  Statement *
   10.16 -Parser::enum_()
   10.17 +Parser::enum_(TokenKind kind)
   10.18  {
   10.19      // enum ::= "enum" name? { enum_members? }
   10.20      // enum_members ::= enum_member ","? |
   10.21 @@ -1229,7 +1229,7 @@
   10.22      if (!expect(TOK_RBRACE))
   10.23          return NULL;
   10.24  
   10.25 -    return new (pool_) EnumStatement(pos, name, entries);
   10.26 +    return new (pool_) EnumStatement(pos, kind, name, entries);
   10.27  }
   10.28  
   10.29  template <class T>
   10.30 @@ -1460,6 +1460,11 @@
   10.31                      return NULL;
   10.32                  if (!matchSemicolon())
   10.33                      return NULL;
   10.34 +            } else if (kind == TOK_PUBLIC && peek(TOK_ENUM)) {
   10.35 +                if ((statement = enum_(kind)) == NULL)
   10.36 +                    return NULL;
   10.37 +                if (!matchSemicolon())
   10.38 +                    return NULL;
   10.39              } else {
   10.40                  if ((statement = function(kind)) == NULL)
   10.41                      return NULL;
   10.42 @@ -1485,7 +1490,7 @@
   10.43            }
   10.44  
   10.45            case TOK_ENUM:
   10.46 -            if ((statement = enum_()) == NULL)
   10.47 +            if ((statement = enum_(TOK_NONE)) == NULL)
   10.48                  return NULL;
   10.49              if (!matchSemicolon())
   10.50                  return NULL;
    11.1 --- a/src/compiler/Parser.h	Sat Jan 12 16:35:26 2013 -0800
    11.2 +++ b/src/compiler/Parser.h	Sun Jan 27 17:34:30 2013 -0800
    11.3 @@ -82,7 +82,7 @@
    11.4  
    11.5      Statement *switch_();
    11.6      Statement *struct_();
    11.7 -    Statement *enum_();
    11.8 +    Statement *enum_(TokenKind kind);
    11.9      Statement *if_();
   11.10      Statement *block();
   11.11      Statement *function(TokenKind tok);
    12.1 --- a/src/compiler/SemanticAnalysis.cpp	Sat Jan 12 16:35:26 2013 -0800
    12.2 +++ b/src/compiler/SemanticAnalysis.cpp	Sun Jan 27 17:34:30 2013 -0800
    12.3 @@ -1103,7 +1103,7 @@
    12.4      if (from->isInt32() && to->isBool())
    12.5          return new (pool_) HConvert(hir->node(), to, OP_CVT_I2B, hir);
    12.6  
    12.7 -    if (to->isEnum() && *from != to)
    12.8 +    if (to->isEnum() && from->unqualified() != to->unqualified())
    12.9          return typeFailure(hir->node()->pos(), from, to);
   12.10      
   12.11      if (to->isArray()) {
   12.12 @@ -1231,10 +1231,10 @@
   12.13              return;
   12.14          }
   12.15  
   12.16 -        if (!IsValidUncheckedType(sym->type())) {
   12.17 +        if (!IsValidUncheckedType(sym->effective())) {
   12.18              char name[255];
   12.19              cc_.reportError(node->pos(), Message_InvalidUncheckedCastTo,
   12.20 -                            GetTypeName(hir->type(), name, sizeof(name)));
   12.21 +                            GetTypeName(sym->type(), name, sizeof(name)));
   12.22              return;
   12.23          }
   12.24          if (!IsValidUncheckedType(hir->type())) {
   12.25 @@ -1244,7 +1244,7 @@
   12.26              return;
   12.27          }
   12.28  
   12.29 -        hir_ = new (pool_) HUnary(node, hir->type(), TOK_LABEL, hir);
   12.30 +        hir_ = new (pool_) HUnary(node, sym->effective(), TOK_LABEL, hir);
   12.31          break;
   12.32        }
   12.33      }
    13.1 --- a/src/compiler/Symbols.h	Sat Jan 12 16:35:26 2013 -0800
    13.2 +++ b/src/compiler/Symbols.h	Sun Jan 27 17:34:30 2013 -0800
    13.3 @@ -160,8 +160,9 @@
    13.4  class TypeSymbol : public Symbol
    13.5  {
    13.6    public:
    13.7 -    TypeSymbol(Scope *scope, Handle<String> name, Handle<Type> type)
    13.8 -      : Symbol(scope, name, SourcePosition())
    13.9 +    TypeSymbol(Scope *scope, Handle<String> name, Handle<Type> type, Handle<Type> effective)
   13.10 +      : Symbol(scope, name, SourcePosition()),
   13.11 +        effective_(effective)
   13.12      {
   13.13          type_ = type;
   13.14      }
   13.15 @@ -169,6 +170,12 @@
   13.16      Kind kind() const {
   13.17          return kType;
   13.18      }
   13.19 +    Handle<Type> effective() {
   13.20 +        return effective_;
   13.21 +    }
   13.22 +
   13.23 +  private:
   13.24 +    ScopedRoot<Type> effective_;
   13.25  };
   13.26  
   13.27  class FunctionSymbol : public Symbol
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tests/basic/import_enum_a.out	Sun Jan 27 17:34:30 2013 -0800
    14.3 @@ -0,0 +1,1 @@
    14.4 +2
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/tests/basic/import_enum_a.sp	Sun Jan 27 17:34:30 2013 -0800
    15.3 @@ -0,0 +1,10 @@
    15.4 +import shell;
    15.5 +import import_enum_b.*;
    15.6 +
    15.7 +public main()
    15.8 +{
    15.9 +    new Crab:crab = TotalCrab;
   15.10 +
   15.11 +    shell.PrintNum(crab);
   15.12 +}
   15.13 +
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/tests/basic/import_enum_b.sp	Sun Jan 27 17:34:30 2013 -0800
    16.3 @@ -0,0 +1,7 @@
    16.4 +public enum Crab
    16.5 +{
    16.6 +    A,
    16.7 +    B,
    16.8 +    TotalCrab
    16.9 +};
   16.10 +