Initial implementation of module imports.
authorDavid Anderson <dvander@alliedmods.net>
Sun Jan 06 13:52:21 2013 -0800 (2013-01-06)
changeset 2563c184218462d
parent 255 b3cf7e052ddf
child 257 9db4cc815ebc
Initial implementation of module imports.
src/Array.cpp
src/Array.h
src/Handles.h
src/Heap-inl.h
src/Interpreter.cpp
src/Messages.tbl
src/Modules.h
src/ObjectVisitor.h
src/Opcodes.cpp
src/Opcodes.tbl
src/Packages.cpp
src/Spaces.h
src/Structures.cpp
src/Structures.h
src/TypeManager.cpp
src/TypeManager.h
src/Types.cpp
src/Types.h
src/Utility.h
src/compiler/AST.h
src/compiler/BytecodeEmitter.h
src/compiler/CompileContext.cpp
src/compiler/HIR.cpp
src/compiler/HIR.h
src/compiler/NameBinding.cpp
src/compiler/Parser.cpp
src/compiler/Scopes.cpp
src/compiler/Scopes.h
src/compiler/SemanticAnalysis.cpp
src/compiler/SemanticAnalysis.h
src/compiler/Symbols.h
tests/basic/import-sysroot-select.out
tests/basic/import-sysroot-select.sp
tests/basic/shell.sp
tests/shell.sp
     1.1 --- a/src/Array.cpp	Tue Jan 01 20:08:34 2013 -0800
     1.2 +++ b/src/Array.cpp	Sun Jan 06 13:52:21 2013 -0800
     1.3 @@ -50,27 +50,6 @@
     1.4      return map;
     1.5  }
     1.6  
     1.7 -ArrayMap *
     1.8 -ArrayMap::Attach(Zone *zone, Handle<ArrayType> type)
     1.9 -{
    1.10 -    if (type->newMap())
    1.11 -        return ArrayMap::cast(type->newMap());
    1.12 -
    1.13 -    Local<ArrayMap> map(zone, ArrayMap::New(zone, type));
    1.14 -    if (!map)
    1.15 -        return NULL;
    1.16 -
    1.17 -    // Ensure the inner type has an ArrayMap if needed.
    1.18 -    if (type->contained()->isArray()) {
    1.19 -        Local<ArrayType> contained(zone, ArrayType::cast(type->contained()));
    1.20 -        if (!ArrayMap::Attach(zone, contained))
    1.21 -            return NULL;
    1.22 -    }
    1.23 -
    1.24 -    type->setNewMap(map);
    1.25 -    return map;
    1.26 -}
    1.27 -
    1.28  Array *
    1.29  Array::NewRaw(Zone *zone, Handle<ArrayMap> map, unsigned nelements, Heap::Tenure tenure)
    1.30  {
     2.1 --- a/src/Array.h	Tue Jan 01 20:08:34 2013 -0800
     2.2 +++ b/src/Array.h	Sun Jan 06 13:52:21 2013 -0800
     2.3 @@ -166,12 +166,7 @@
     2.4      Barriered<ArrayType> type_;
     2.5  
     2.6    public:
     2.7 -    // The way array maps work is kind of clownshoes. In the future, these
     2.8 -    // should be created immediately (or lazily) on the Type directly, and not
     2.9 -    // manually created via ::Attach. :TODO: do this when we begin caching
    2.10 -    // array types.
    2.11      static ArrayMap *New(Zone *zone, Handle<ArrayType> type);
    2.12 -    static ArrayMap *Attach(Zone *zone, Handle<ArrayType> type);
    2.13  
    2.14      // DependentArray maps are never attached, and are just free-floating,
    2.15      // rooted ultimately by the bytecode. A :TODO: that we might need to
     3.1 --- a/src/Handles.h	Tue Jan 01 20:08:34 2013 -0800
     3.2 +++ b/src/Handles.h	Sun Jan 06 13:52:21 2013 -0800
     3.3 @@ -170,7 +170,7 @@
     3.4  // A ScopedRoot is a special kind of handle for storing references on the
     3.5  // heap in bulk.
     3.6  template <typename T>
     3.7 -class ScopedRoot
     3.8 +class ScopedRoot : public PoolObject
     3.9  {
    3.10      T **thingp_;
    3.11  
     4.1 --- a/src/Heap-inl.h	Tue Jan 01 20:08:34 2013 -0800
     4.2 +++ b/src/Heap-inl.h	Sun Jan 06 13:52:21 2013 -0800
     4.3 @@ -75,7 +75,7 @@
     4.4      size_t actualBytes = Align(bytes, kObjectAlignment);
     4.5  
     4.6      // All objects must be at least two words.
     4.7 -    assert(actualBytes >= sizeof(Object *) * 2);
     4.8 +    assert(actualBytes >= kMinObjectSize);
     4.9  
    4.10      Address address = newObject(actualBytes, age);
    4.11      if (!address) {
     5.1 --- a/src/Interpreter.cpp	Tue Jan 01 20:08:34 2013 -0800
     5.2 +++ b/src/Interpreter.cpp	Sun Jan 06 13:52:21 2013 -0800
     5.3 @@ -898,7 +898,11 @@
     5.4  
     5.5  case OP_GETFIELD:
     5.6  {
     5.7 -    Struct *obj = Struct::cast(top.sp[-1].obj);
     5.8 +    Struct *obj;
     5.9 +    if (top.sp[-1].obj->is(MapKind_Module))
    5.10 +        obj = Module::cast(top.sp[-1].obj)->globals();
    5.11 +    else
    5.12 +        obj = Struct::cast(top.sp[-1].obj);
    5.13      GetField(obj, READ_UINT32(top.pc), &top.sp[-1]);
    5.14      break;
    5.15  }
    5.16 @@ -1007,6 +1011,15 @@
    5.17      break;
    5.18  }
    5.19  
    5.20 +case OP_IMPORT:
    5.21 +{
    5.22 +    unsigned index = READ_UINT32(top.pc);
    5.23 +
    5.24 +    top.sp++;
    5.25 +    top.sp[-1].obj = top.fp->code()->module()->getImportAt(index);
    5.26 +    break;
    5.27 +}
    5.28 +
    5.29  default:
    5.30      assert(false);
    5.31      return false;
     6.1 --- a/src/Messages.tbl	Tue Jan 01 20:08:34 2013 -0800
     6.2 +++ b/src/Messages.tbl	Sun Jan 06 13:52:21 2013 -0800
     6.3 @@ -85,4 +85,9 @@
     6.4  MSG(InvalidUncheckedCastFrom,       TypeError,              "cannot perform an unchecked cast on type '%s'")
     6.5  MSG(InvalidUncheckedCastTo,         TypeError,              "cannot perform an unchecked cast to type '%s'")
     6.6  MSG(InvalidUnaryType,               TypeError,              "operator %s not defined for type '%s'")
     6.7 -MSG(CannotImportPath,               SyntaxError,            "could not find module or import '%s'")
     6.8 \ No newline at end of file
     6.9 +MSG(CannotImportPath,               SyntaxError,            "could not find module or import '%s'")
    6.10 +MSG(DuplicateImport,                SyntaxError,            "duplicate import name '%s'")
    6.11 +MSG(InvalidFieldExpression,			TypeError,				"type '%s' does not have any fields")
    6.12 +MSG(PackageDoesNotHaveMember,		TypeError,				"package does not have member '%s' (check imports)")
    6.13 +MSG(ImportWasNeverImported,         TypeError,              "'%s' was never imported")
    6.14 +MSG(FieldNotFound,                  TypeError,              "field '%s' not found")
    6.15 \ No newline at end of file
     7.1 --- a/src/Modules.h	Tue Jan 01 20:08:34 2013 -0800
     7.2 +++ b/src/Modules.h	Sun Jan 06 13:52:21 2013 -0800
     7.3 @@ -21,6 +21,7 @@
     7.4  #include "Heap.h"
     7.5  #include "Code.h"
     7.6  #include "Functions.h"
     7.7 +#include "FixedArray.h"
     7.8  #include "Packages.h"
     7.9  
    7.10  namespace ke {
    7.11 @@ -36,6 +37,7 @@
    7.12      Barriered<Struct> globals_;
    7.13      void *nativeIdentity_;
    7.14      TranslationUnit *unit_;
    7.15 +    Barriered<FixedArray> imports_;
    7.16  
    7.17    public:
    7.18      static Module *New(Zone *zone, Handle<Package> package, Handle<String> path, Handle<String> name);
    7.19 @@ -63,6 +65,18 @@
    7.20          unit_ = unit;
    7.21      }
    7.22  
    7.23 +    unsigned imports() {
    7.24 +        return imports_ ? imports_->length() / 2 : 0;
    7.25 +    }
    7.26 +    Importable *getImportAt(unsigned index) {
    7.27 +        return Importable::cast(imports_->at(index * 2));
    7.28 +    }
    7.29 +    FixedArray *importPathAt(unsigned index) {
    7.30 +        return FixedArray::cast(imports_->at(index * 2 + 1));
    7.31 +    }
    7.32 +    void setImports(Handle<FixedArray> imports) {
    7.33 +        imports_ = imports;
    7.34 +    }
    7.35      void setCode(Handle<Code> code) {
    7.36          code_ = code;
    7.37      }
    7.38 @@ -77,6 +91,9 @@
    7.39      static inline size_t offsetOfGlobals() {
    7.40          return OFFSETOF(Module, globals_);
    7.41      }
    7.42 +    static inline size_t offsetOfImports() {
    7.43 +        return OFFSETOF(Module, imports_);
    7.44 +    }
    7.45      // End GC Descriptor.
    7.46  
    7.47      static inline Module *cast(Object *obj) {
     8.1 --- a/src/ObjectVisitor.h	Tue Jan 01 20:08:34 2013 -0800
     8.2 +++ b/src/ObjectVisitor.h	Sun Jan 06 13:52:21 2013 -0800
     8.3 @@ -125,6 +125,7 @@
     8.4          visitImportable(obj);
     8.5          visitField(obj, Module::offsetOfGlobals());
     8.6          visitField(obj, Module::offsetOfCode());
     8.7 +        visitField(obj, Module::offsetOfImports());
     8.8          return sizeof(Module);
     8.9      }
    8.10  
    8.11 @@ -213,7 +214,7 @@
    8.12          unsigned noffsets = map->traceOffsetCount();
    8.13          for (unsigned i = 0; i < noffsets; i++)
    8.14              visitField(obj, Struct::offsetOfSlotOffset(offsets[i]));
    8.15 -        return obj->objSize();
    8.16 +        return Struct::SizeFor(map);
    8.17      }
    8.18  
    8.19      size_t iterateList(Object *obj) {
    8.20 @@ -388,7 +389,7 @@
    8.21          return sizeof(List<Object>);
    8.22  
    8.23        case MapKind_Struct:
    8.24 -        return Struct::cast(obj)->objSize();
    8.25 +        return Struct::SizeFor(StructMap::cast(map));
    8.26  
    8.27        case MapKind_EnvironmentSlotDescriptorArray:
    8.28          return EnvironmentSlotDescriptorArray::cast(obj)->objSize();
     9.1 --- a/src/Opcodes.cpp	Tue Jan 01 20:08:34 2013 -0800
     9.2 +++ b/src/Opcodes.cpp	Sun Jan 06 13:52:21 2013 -0800
     9.3 @@ -25,6 +25,7 @@
     9.4  #include "Strings.h"
     9.5  #include "CompactBuffer.h"
     9.6  #include "Structures.h"
     9.7 +#include "Modules.h"
     9.8  #include "Heap-inl.h"
     9.9  
    9.10  using namespace ke;
    9.11 @@ -304,6 +305,19 @@
    9.12              break;
    9.13            }
    9.14  
    9.15 +          case OP_IMPORT:
    9.16 +          {
    9.17 +            unsigned index = READ_UINT32(pc);
    9.18 +            FixedArray *path = code->module()->importPathAt(index);
    9.19 +            fprintf(fp, " ; ");
    9.20 +            for (unsigned i = 0; i < path->length(); i++) {
    9.21 +                fprintf(fp, "%s", String::cast(path->at(i))->chars());
    9.22 +                if (i != path->length() - 1)
    9.23 +                    fprintf(fp, ".");
    9.24 +            }
    9.25 +            break;
    9.26 +          }
    9.27 +
    9.28            default:
    9.29              // Unknown opcode!
    9.30              assert(false);
    10.1 --- a/src/Opcodes.tbl	Tue Jan 01 20:08:34 2013 -0800
    10.2 +++ b/src/Opcodes.tbl	Sun Jan 06 13:52:21 2013 -0800
    10.3 @@ -265,4 +265,7 @@
    10.4  //  index = POP()
    10.5  //  base = POP()
    10.6  //  PUSH(array)
    10.7 -OPDEF(OP_DEPARRAY,      "deparray",     5,      2, 1)
    10.8 \ No newline at end of file
    10.9 +OPDEF(OP_DEPARRAY,      "deparray",     5,      2, 1)
   10.10 +
   10.11 +// Grabs an import object from the import table.
   10.12 +OPDEF(OP_IMPORT,        "import",       5,      0, 1)
   10.13 \ No newline at end of file
    11.1 --- a/src/Packages.cpp	Tue Jan 01 20:08:34 2013 -0800
    11.2 +++ b/src/Packages.cpp	Sun Jan 06 13:52:21 2013 -0800
    11.3 @@ -69,6 +69,12 @@
    11.4              return false;
    11.5      }
    11.6  
    11.7 +#ifndef NDEBUG
    11.8 +    // Assert no duplicate names.
    11.9 +    for (unsigned i = 0; i < pkg->contents_->length(); i++)
   11.10 +        assert(pkg->contents_->at(i)->name() != obj->name());
   11.11 +#endif
   11.12 +
   11.13      if (!pkg->contents_->append(zone, obj))
   11.14          return false;
   11.15  
    12.1 --- a/src/Spaces.h	Tue Jan 01 20:08:34 2013 -0800
    12.2 +++ b/src/Spaces.h	Sun Jan 06 13:52:21 2013 -0800
    12.3 @@ -30,6 +30,7 @@
    12.4  class Map;
    12.5  
    12.6  static const size_t kObjectAlignment = sizeof(Object *);
    12.7 +static const size_t kMinObjectSize   = sizeof(Object *) * 2;
    12.8  
    12.9  // Every object gets two successive mark bits. These bits represent various
   12.10  // states during garbage collection:
    13.1 --- a/src/Structures.cpp	Tue Jan 01 20:08:34 2013 -0800
    13.2 +++ b/src/Structures.cpp	Sun Jan 06 13:52:21 2013 -0800
    13.3 @@ -56,7 +56,7 @@
    13.4  }
    13.5  
    13.6  Descriptor *
    13.7 -Descriptor::New(Zone *zone, Handle<String> name, Handle<Type> type)
    13.8 +Descriptor::New(Zone *zone, Handle<String> name, Handle<Type> type, Visibility visibility)
    13.9  {
   13.10      Local<Descriptor> desc(zone,
   13.11          Descriptor::cast(zone->allocate(MapKind_Descriptor, sizeof(Descriptor), Heap::Tenure_Old)));
   13.12 @@ -66,6 +66,7 @@
   13.13      desc->name_ = name;
   13.14      desc->type_ = type;
   13.15      desc->offset_ = unsigned(-1);
   13.16 +    desc->visibility_ = visibility;
   13.17      return desc;
   13.18  }
   13.19  
   13.20 @@ -111,12 +112,13 @@
   13.21  Struct *
   13.22  Struct::New(Zone *zone, Handle<StructMap> map, Heap::Tenure tenure)
   13.23  {
   13.24 -    size_t bytesNeeded = sizeof(Struct) + map->structureSize();
   13.25 +    size_t bytesNeeded = SizeFor(map);
   13.26 +
   13.27      Local<Struct> obj(zone, Struct::cast(zone->allocate(map, bytesNeeded, tenure)));
   13.28      if (!obj)
   13.29          return NULL;
   13.30  
   13.31 -    memset((Struct *)obj + 1, 0, map->structureSize());
   13.32 +    memset((Struct *)obj + 1, 0, (bytesNeeded - sizeof(Struct)));
   13.33  
   13.34      // Initialize any sub-structures. Right now, this is performed as part of
   13.35      // struct allocation, rather than inlined in bytecode, for simplicity.
    14.1 --- a/src/Structures.h	Tue Jan 01 20:08:34 2013 -0800
    14.2 +++ b/src/Structures.h	Sun Jan 06 13:52:21 2013 -0800
    14.3 @@ -60,6 +60,14 @@
    14.4  // Represents a property descriptor for a structure field.
    14.5  class Descriptor : public Object
    14.6  {
    14.7 +  public:
    14.8 +    enum Visibility {
    14.9 +        Private,
   14.10 +        Protected,
   14.11 +        Public
   14.12 +    };
   14.13 +
   14.14 +  private:
   14.15      // The name of the field.
   14.16      Barriered<String> name_;
   14.17  
   14.18 @@ -69,8 +77,10 @@
   14.19      // The offset into an object at which this field can be accessed.
   14.20      unsigned offset_;
   14.21  
   14.22 +    Visibility visibility_;
   14.23 +
   14.24    public:
   14.25 -    static Descriptor *New(Zone *zone, Handle<String> name, Handle<Type> type);
   14.26 +    static Descriptor *New(Zone *zone, Handle<String> name, Handle<Type> type, Visibility visibility);
   14.27  
   14.28      String *name() {
   14.29          return name_;
   14.30 @@ -160,9 +170,6 @@
   14.31  
   14.32      static bool Copy(Zone *zone, Handle<Struct> dest, Handle<Struct> src);
   14.33  
   14.34 -    size_t objSize() {
   14.35 -        return sizeof(Struct) + map()->structureSize();
   14.36 -    }
   14.37      StructMap *map() {
   14.38          return StructMap::cast(Object::map());
   14.39      }
   14.40 @@ -171,6 +178,10 @@
   14.41          return reinterpret_cast<Address>(this) + offsetOfSlotOffset(desc->offset());
   14.42      }
   14.43  
   14.44 +    static inline size_t SizeFor(StructMap *map) {
   14.45 +        return Max(sizeof(Struct) + map->structureSize(), kMinObjectSize);
   14.46 +    }
   14.47 +
   14.48      template <typename T> T get(Descriptor *desc) {
   14.49          return *reinterpret_cast<T *>(ref(desc));
   14.50      }
    15.1 --- a/src/TypeManager.cpp	Tue Jan 01 20:08:34 2013 -0800
    15.2 +++ b/src/TypeManager.cpp	Sun Jan 06 13:52:21 2013 -0800
    15.3 @@ -48,6 +48,10 @@
    15.4      if (!stringType_)
    15.5          return false;
    15.6  
    15.7 +    importableType_ = Type::NewImportable(zone_);
    15.8 +    if (!importableType_)
    15.9 +        return false;
   15.10 +
   15.11      if ((primitiveTypes_[PrimitiveType_Int32] = Type::NewPrimitive(zone_, PrimitiveType_Int32)) == NULL)
   15.12          return false;
   15.13      if ((primitiveTypes_[PrimitiveType_Float] = Type::NewPrimitive(zone_, PrimitiveType_Float)) == NULL)
   15.14 @@ -136,6 +140,7 @@
   15.15      visitor->visit(voidType_.address());
   15.16      visitor->visit(uncheckedType_.address());
   15.17      visitor->visit(stringType_.address());
   15.18 +    visitor->visit(importableType_.address());
   15.19      for (unsigned i = 0; i < PrimitiveTypes_Total; i++) {
   15.20          visitor->visit(primitiveTypes_[i].address());
   15.21          visitor->visit(referenceTypes_[i].address());
    16.1 --- a/src/TypeManager.h	Tue Jan 01 20:08:34 2013 -0800
    16.2 +++ b/src/TypeManager.h	Sun Jan 06 13:52:21 2013 -0800
    16.3 @@ -79,6 +79,9 @@
    16.4      Type *getUnchecked() {
    16.5          return uncheckedType_;
    16.6      }
    16.7 +    Type *getImportable() {
    16.8 +        return importableType_;
    16.9 +    }
   16.10      ReferenceType *getReference(Handle<Type> type, bool isConst);
   16.11      ArrayType *newArray(Handle<Type> contained, int elements);
   16.12      ArrayType *newExternalArray(Handle<Type> contained);
   16.13 @@ -96,6 +99,7 @@
   16.14      Unbarriered<Type> voidType_;
   16.15      Unbarriered<Type> stringType_;
   16.16      Unbarriered<Type> uncheckedType_;
   16.17 +    Unbarriered<Type> importableType_;
   16.18      Unbarriered<Type> primitiveTypes_[PrimitiveTypes_Total];
   16.19      Unbarriered<ReferenceType> referenceTypes_[PrimitiveTypes_Total];
   16.20  
    17.1 --- a/src/Types.cpp	Tue Jan 01 20:08:34 2013 -0800
    17.2 +++ b/src/Types.cpp	Sun Jan 06 13:52:21 2013 -0800
    17.3 @@ -20,6 +20,7 @@
    17.4  #include "Types.h"
    17.5  #include "Zone.h"
    17.6  #include "Strings.h"
    17.7 +#include "Array.h"
    17.8  #include "Structures.h"
    17.9  #include "Heap-inl.h"
   17.10  
   17.11 @@ -44,6 +45,17 @@
   17.12  }
   17.13  
   17.14  Type *
   17.15 +Type::NewImportable(Zone *zone)
   17.16 +{
   17.17 +    Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   17.18 +    if (!type)
   17.19 +        return NULL;
   17.20 +
   17.21 +    type->init(IMPORTABLE);
   17.22 +    return type;
   17.23 +}
   17.24 +
   17.25 +Type *
   17.26  Type::NewString(Zone *zone)
   17.27  {
   17.28      Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   17.29 @@ -110,6 +122,11 @@
   17.30          type->levels_ = 1;
   17.31      else
   17.32          type->levels_ = ArrayType::cast(contained)->levels() + 1;
   17.33 +
   17.34 +    type->newMap_ = ArrayMap::New(zone, type);
   17.35 +    if (!type->newMap_)
   17.36 +        return NULL;
   17.37 +
   17.38      return type;
   17.39  }
   17.40  
   17.41 @@ -270,6 +287,8 @@
   17.42          return Format(buffer, maxlen, "void");
   17.43      if (type->isUnchecked())
   17.44          return Format(buffer, maxlen, "unchecked");
   17.45 +    if (type->isImportable())
   17.46 +        return Format(buffer, maxlen, "import");
   17.47      if (type->isEnum())
   17.48          return Format(buffer, maxlen, "%s", EnumType::cast(type)->name()->chars());
   17.49      if (type->isStruct())
    18.1 --- a/src/Types.h	Tue Jan 01 20:08:34 2013 -0800
    18.2 +++ b/src/Types.h	Sun Jan 06 13:52:21 2013 -0800
    18.3 @@ -111,7 +111,11 @@
    18.4  
    18.5          // Structs are composite records that may contain primitives, arrays,
    18.6          // functions, enums, and other structs.
    18.7 -        STRUCT
    18.8 +        STRUCT,
    18.9 +
   18.10 +        // Importable types are mainly used during the compilation process
   18.11 +        // to distinguish between normal names and static imports.
   18.12 +        IMPORTABLE
   18.13      };
   18.14  
   18.15      void init(Kind kind, Type *root = NULL);
   18.16 @@ -127,6 +131,7 @@
   18.17      static Type *NewPrimitive(Zone *zone, PrimitiveType type);
   18.18      static Type *NewString(Zone *zone);
   18.19      static Type *NewQualified(Zone *zone, TypeQualifiers qual, Handle<Type> type);
   18.20 +    static Type *NewImportable(Zone *zone);
   18.21  
   18.22      static Type *cast(Object *obj) {
   18.23          assert(!obj ||
   18.24 @@ -160,6 +165,9 @@
   18.25      bool isStruct() {
   18.26          return kind() == STRUCT;
   18.27      }
   18.28 +    bool isImportable() {
   18.29 +        return kind() == IMPORTABLE;
   18.30 +    }
   18.31      PrimitiveType primitive() {
   18.32          assert(isPrimitive());
   18.33          return root_->primitive_;
    19.1 --- a/src/Utility.h	Tue Jan 01 20:08:34 2013 -0800
    19.2 +++ b/src/Utility.h	Sun Jan 06 13:52:21 2013 -0800
    19.3 @@ -282,6 +282,12 @@
    19.4      return t1 < t2 ? t1 : t2;
    19.5  }
    19.6  
    19.7 +template <typename T> static inline T
    19.8 +Max(const T &t1, const T &t2)
    19.9 +{
   19.10 +    return t1 > t2 ? t1 : t2;
   19.11 +}
   19.12 +
   19.13  #define OFFSETOF(Class, Member) reinterpret_cast<size_t>(&((Class *)NULL)->Member)
   19.14  
   19.15  }
    20.1 --- a/src/compiler/AST.h	Tue Jan 01 20:08:34 2013 -0800
    20.2 +++ b/src/compiler/AST.h	Sun Jan 06 13:52:21 2013 -0800
    20.3 @@ -28,6 +28,7 @@
    20.4  namespace ke {
    20.5  
    20.6  class Scope;
    20.7 +class Importable;
    20.8  struct PathComponent;
    20.9  
   20.10  #define ASTKINDS(_)             \
   20.11 @@ -128,21 +129,11 @@
   20.12  
   20.13  class Expression : public AstNode
   20.14  {
   20.15 -    ScopedRoot<Type> type_;
   20.16 -
   20.17    public:
   20.18      Expression(const SourcePosition &pos)
   20.19 -      : AstNode(pos),
   20.20 -        type_(NULL)
   20.21 +      : AstNode(pos)
   20.22      {
   20.23      }
   20.24 -
   20.25 -    void setType(Type *type) {
   20.26 -        type_ = type;
   20.27 -    }
   20.28 -    Type *type() const {
   20.29 -        return type_;
   20.30 -    }
   20.31  };
   20.32  
   20.33  typedef PoolList<Statement *> StatementList;
   20.34 @@ -497,14 +488,12 @@
   20.35  {
   20.36      Expression *left_;
   20.37      ScopedRoot<String> field_;
   20.38 -    unsigned fieldIndex_;
   20.39  
   20.40    public:
   20.41      FieldExpression(const SourcePosition &pos, Expression *left, Handle<String> field)
   20.42        : Expression(pos),
   20.43          left_(left),
   20.44 -        field_(field),
   20.45 -        fieldIndex_(unsigned(-1))
   20.46 +        field_(field)
   20.47      {
   20.48      }
   20.49  
   20.50 @@ -513,17 +502,9 @@
   20.51      Expression *left() const {
   20.52          return left_;
   20.53      }
   20.54 -    String *field() const {
   20.55 +    Handle<String> field() const {
   20.56          return field_;
   20.57      }
   20.58 -    void setFieldIndex(unsigned index) {
   20.59 -        assert(fieldIndex_ == unsigned(-1));
   20.60 -        fieldIndex_ = index;
   20.61 -    }
   20.62 -    unsigned fieldIndex() const {
   20.63 -        assert(fieldIndex_ != unsigned(-1));
   20.64 -        return fieldIndex_;
   20.65 -    }
   20.66  };
   20.67  
   20.68  class CallExpression : public Expression
   20.69 @@ -1105,11 +1086,9 @@
   20.70  class ImportStatement : public Statement
   20.71  {
   20.72    public:
   20.73 -    ImportStatement(const SourcePosition &pos, PathComponent *path, TokenKind suffix)
   20.74 +    ImportStatement(const SourcePosition &pos, PathComponent *path)
   20.75        : Statement(pos),
   20.76 -        path_(path),
   20.77 -        suffix_(suffix),
   20.78 -        source_(NULL)
   20.79 +        path_(path)
   20.80      {
   20.81      }
   20.82  
   20.83 @@ -1118,20 +1097,23 @@
   20.84      PathComponent *path() const {
   20.85          return path_;
   20.86      }
   20.87 -    void setImportSource(TranslationUnit *unit) {
   20.88 -        source_ = unit;
   20.89 +    void setSource(Importable *source) {
   20.90 +        source_ = source;
   20.91      }
   20.92 -    TranslationUnit *source() const {
   20.93 +    Handle<Importable> source() {
   20.94          return source_;
   20.95      }
   20.96 -    TokenKind suffix() const {
   20.97 -        return suffix_;
   20.98 +    unsigned importIndex() {
   20.99 +        return importIndex_;
  20.100 +    }
  20.101 +    void setImportIndex(unsigned index) {
  20.102 +        importIndex_ = index;
  20.103      }
  20.104  
  20.105    private:
  20.106      PathComponent *path_;
  20.107 -    TokenKind suffix_;
  20.108 -    TranslationUnit *source_;
  20.109 +    ScopedRoot<Importable> source_;
  20.110 +    unsigned importIndex_;
  20.111  };
  20.112  
  20.113  typedef StructureStatement::FieldList FieldList;
    21.1 --- a/src/compiler/BytecodeEmitter.h	Tue Jan 01 20:08:34 2013 -0800
    21.2 +++ b/src/compiler/BytecodeEmitter.h	Sun Jan 06 13:52:21 2013 -0800
    21.3 @@ -681,6 +681,13 @@
    21.4              jump(labels[i]);
    21.5      }
    21.6  
    21.7 +    void import(unsigned index) {
    21.8 +        ensure(OP_IMPORT_LENGTH);
    21.9 +        writeOp(OP_IMPORT);
   21.10 +        writeUint32(index);
   21.11 +        markOop(1);
   21.12 +    }
   21.13 +
   21.14      bool allocate(VariableSymbol *sym);
   21.15  
   21.16      Code *finish();
    22.1 --- a/src/compiler/CompileContext.cpp	Tue Jan 01 20:08:34 2013 -0800
    22.2 +++ b/src/compiler/CompileContext.cpp	Sun Jan 06 13:52:21 2013 -0800
    22.3 @@ -21,6 +21,8 @@
    22.4  #include "../Interpreter.h"
    22.5  #include "../Packages.h"
    22.6  #include "../FileSystem.h"
    22.7 +#include "../FixedArray.h"
    22.8 +#include "../Vector.h"
    22.9  #include "Scanner.h"
   22.10  #include "CompileContext.h"
   22.11  #include "Parser.h"
   22.12 @@ -60,7 +62,7 @@
   22.13      if (!strname)
   22.14          return false;
   22.15  
   22.16 -    PathComponent p(new ScopedRoot<String>(strname), NULL);
   22.17 +    PathComponent p(new (zone_->pool()) ScopedRoot<String>(strname), NULL);
   22.18  
   22.19      Local<Importable> importable(zone_);
   22.20      if (!zone_->packages()->findOrAdd(package, &p, importable.address()))
   22.21 @@ -145,10 +147,17 @@
   22.22  {
   22.23      PoolList<ImportStatement *> *imports = unit->tree()->imports();
   22.24  
   22.25 +    if (!imports->length())
   22.26 +        return true;
   22.27 +
   22.28 +    // We're allowed to use Handle<> here instead of ScopedRoot<> because
   22.29 +    // we get the handle from ImportStatement which has a ScopedRoot<>.
   22.30 +    Vector<Handle<Importable> > vec;
   22.31 +
   22.32      for (size_t i = 0; i < imports->length(); i++) {
   22.33          ImportStatement *import = imports->at(i);
   22.34  
   22.35 -        // Step 1. Crawl the path until we find a valid file to load.
   22.36 +        // Crawl the path until we find a valid file to load.
   22.37          Local<Importable> obj(zone_);
   22.38          Local<Package> package(zone_, unit->module()->parent());
   22.39          if (!zone_->packages()->findOrAdd(package, import->path(), obj.address()))
   22.40 @@ -170,8 +179,52 @@
   22.41              if (!add(module))
   22.42                  return false;
   22.43          }
   22.44 +
   22.45 +        import->setSource(obj);
   22.46 +        
   22.47 +        // See if there are any duplicates. This is O(n^2), but we expect
   22.48 +        // |n| to be small.
   22.49 +        unsigned index = 0;
   22.50 +        for (; index < vec.length(); index++) {
   22.51 +            if (vec[index] == obj)
   22.52 +                break;
   22.53 +        }
   22.54 +        if (index == vec.length() && !vec.append(import->source()))
   22.55 +            return false;
   22.56 +
   22.57 +        import->setImportIndex(index);
   22.58      }
   22.59  
   22.60 +    if (!IsUint32MultiplySafe(vec.length(), 2)) {
   22.61 +        zone_->reportAllocationOverflow();
   22.62 +        return false;
   22.63 +    }
   22.64 +
   22.65 +    // Create an array of the import and paths.
   22.66 +    Local<FixedArray> importables(zone_, FixedArray::New(zone_, vec.length() * 2, Heap::Tenure_Default));
   22.67 +    if (!importables)
   22.68 +        return false;
   22.69 +
   22.70 +    for (unsigned i = 0; i < vec.length(); i++) {
   22.71 +        importables->set(zone_, i * 2, vec[i]);
   22.72 +
   22.73 +        unsigned count = 0;
   22.74 +        PathComponent *path = imports->at(i)->path();
   22.75 +        for (PathComponent *iter = path; iter; iter = iter->next)
   22.76 +            count++;
   22.77 +
   22.78 +        Local<FixedArray> list(zone_, FixedArray::New(zone_, count, Heap::Tenure_Default));
   22.79 +        if (!list)
   22.80 +            return false;
   22.81 +
   22.82 +        count = 0;
   22.83 +        for (PathComponent *iter = path; iter; iter = iter->next, count++)
   22.84 +            list->set(zone_, count, iter->name);
   22.85 +
   22.86 +        importables->set(zone_, i * 2 + 1, list);
   22.87 +    }
   22.88 +
   22.89 +    unit->module()->setImports(importables);
   22.90      return true;
   22.91  }
   22.92  
    23.1 --- a/src/compiler/HIR.cpp	Tue Jan 01 20:08:34 2013 -0800
    23.2 +++ b/src/compiler/HIR.cpp	Sun Jan 06 13:52:21 2013 -0800
    23.3 @@ -50,9 +50,11 @@
    23.4      void visitGlobal(HGlobal *global);
    23.5      void visitConvert(HConvert *convert);
    23.6      void visitIndex(HIndex *index);
    23.7 +    void visitField(HField *field);
    23.8      void visitPostIncDec(HPostIncDec *hir);
    23.9      void visitToRef(HToRef *hir);
   23.10      void visitNewDependentArray(HNewDependentArray *hir);
   23.11 +    void visitImport(HImport *import);
   23.12  
   23.13    private:
   23.14      Zone *zone_;
   23.15 @@ -286,6 +288,45 @@
   23.16  }
   23.17  
   23.18  void
   23.19 +HField::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
   23.20 +{
   23.21 +    __ note_position(node()->pos());
   23.22 +    base_->accept(visitor);
   23.23 +}
   23.24 +
   23.25 +void
   23.26 +HField::hold(BytecodeEmitter &emitter_)
   23.27 +{
   23.28 +    __ dup();
   23.29 +}
   23.30 +
   23.31 +void
   23.32 +HField::swapAndPick(BytecodeEmitter &emitter_)
   23.33 +{
   23.34 +    // BASE VALUE
   23.35 +    __ swap();      // VALUE BASE
   23.36 +    __ pick2();     // VALUE BASE VALUE
   23.37 +}
   23.38 +
   23.39 +void
   23.40 +HField::store(BytecodeEmitter &emitter_)
   23.41 +{
   23.42 +    __ setfield(index_, type());
   23.43 +}
   23.44 +
   23.45 +void
   23.46 +HField::load(BytecodeEmitter &emitter_)
   23.47 +{
   23.48 +    __ getfield(index_, type());
   23.49 +}
   23.50 +
   23.51 +bool
   23.52 +HField::ref(BytecodeEmitter &emitter_)
   23.53 +{
   23.54 +    return false;
   23.55 +}
   23.56 +
   23.57 +void
   23.58  HIRTranslator::visitLocal(HLocal *local)
   23.59  {
   23.60      local->bind(this, emitter_);
   23.61 @@ -300,6 +341,13 @@
   23.62  }
   23.63  
   23.64  void
   23.65 +HIRTranslator::visitField(HField *field)
   23.66 +{
   23.67 +    field->bind(this, emitter_);
   23.68 +    field->load(emitter_);
   23.69 +}
   23.70 +
   23.71 +void
   23.72  HIRTranslator::visitGlobal(HGlobal *global)
   23.73  {
   23.74      global->bind(this, emitter_);
   23.75 @@ -486,11 +534,6 @@
   23.76  
   23.77      Local<ArrayType> type(zone_, ArrayType::cast(hir->type()));
   23.78  
   23.79 -    // Attach an actual map to the dependent type, in case it's a new
   23.80 -    // type.
   23.81 -    if (!ArrayMap::Attach(zone_, type))
   23.82 -        return;
   23.83 -
   23.84      // The dependent map is used for the opcode, but is not attached.
   23.85      Local<ArrayMap> map(zone_, ArrayMap::NewDependent(zone_, type));
   23.86      if (!map)
   23.87 @@ -500,6 +543,12 @@
   23.88  }
   23.89  
   23.90  void
   23.91 +HIRTranslator::visitImport(HImport *import)
   23.92 +{
   23.93 +    __ import(import->index());
   23.94 +}
   23.95 +
   23.96 +void
   23.97  ke::EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir)
   23.98  {
   23.99      HIRTranslator translator(zone, emitter);
    24.1 --- a/src/compiler/HIR.h	Tue Jan 01 20:08:34 2013 -0800
    24.2 +++ b/src/compiler/HIR.h	Sun Jan 06 13:52:21 2013 -0800
    24.3 @@ -31,6 +31,7 @@
    24.4      _(Integer)                          \
    24.5      _(Float)                            \
    24.6      _(String)                           \
    24.7 +    _(Import)                           \
    24.8      _(Array)                            \
    24.9      _(Store)                            \
   24.10      _(ToRef)                            \
   24.11 @@ -39,6 +40,7 @@
   24.12      _(Index)                            \
   24.13      _(Local)                            \
   24.14      _(Global)                           \
   24.15 +    _(Field)                            \
   24.16      /* End LValues */                   \
   24.17      _(Unary)                            \
   24.18      _(Binary)                           \
   24.19 @@ -184,6 +186,24 @@
   24.20      ScopedRoot<String> string_;
   24.21  };
   24.22  
   24.23 +class HImport : public HIR
   24.24 +{
   24.25 +  public:
   24.26 +    HImport(AstNode *node, Type *type, unsigned index)
   24.27 +      : HIR(node, type),
   24.28 +        index_(index)
   24.29 +    {
   24.30 +    }
   24.31 +
   24.32 +    DEFINE_HIR(Import);
   24.33 +    unsigned index() const {
   24.34 +        return index_;
   24.35 +    }
   24.36 +
   24.37 +  private:
   24.38 +    unsigned index_;
   24.39 +};
   24.40 +
   24.41  class HArray : public HIR
   24.42  {
   24.43    public:
   24.44 @@ -319,6 +339,37 @@
   24.45      HIR *right_;
   24.46  };
   24.47  
   24.48 +class HField : public HLValue
   24.49 +{
   24.50 +  public:
   24.51 +    HField(AstNode *node, HIR *left, Type *type, unsigned index)
   24.52 +      : HLValue(node, type),
   24.53 +        base_(left),
   24.54 +        index_(index)
   24.55 +    {
   24.56 +    }
   24.57 +
   24.58 +    DEFINE_HIR(Field);
   24.59 +
   24.60 +    void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_);
   24.61 +    void hold(BytecodeEmitter &emitter_);
   24.62 +    void swapAndPick(BytecodeEmitter &emitter_);
   24.63 +    void store(BytecodeEmitter &emitter_);
   24.64 +    void load(BytecodeEmitter &emitter_);
   24.65 +    bool ref(BytecodeEmitter &emitter_);
   24.66 +
   24.67 +    HIR *base() const {
   24.68 +        return base_;
   24.69 +    }
   24.70 +    unsigned index() const {
   24.71 +        return index_;
   24.72 +    }
   24.73 +
   24.74 +  private:
   24.75 +    HIR *base_;
   24.76 +    unsigned index_;
   24.77 +};
   24.78 +
   24.79  class HGlobal : public HLValue
   24.80  {
   24.81    public:
    25.1 --- a/src/compiler/NameBinding.cpp	Tue Jan 01 20:08:34 2013 -0800
    25.2 +++ b/src/compiler/NameBinding.cpp	Sun Jan 06 13:52:21 2013 -0800
    25.3 @@ -197,6 +197,7 @@
    25.4          if (node->initialization())
    25.5              node->initialization()->accept(this);
    25.6      }
    25.7 +
    25.8      void visitEnumStatement(EnumStatement *node) {
    25.9          Local<String> name(zone_, node->name());
   25.10          Local<Type> type(zone_);
   25.11 @@ -239,6 +240,7 @@
   25.12              value++;
   25.13          }
   25.14      }
   25.15 +
   25.16      void visitFunctionStatement(FunctionStatement *node) {
   25.17          // We create function types ahead of time, not for any particular
   25.18          // reason. It makes things consistent with FunctionTypeStatement,
   25.19 @@ -260,9 +262,6 @@
   25.20          {
   25.21              // We're in the global scope, for sure.
   25.22              assert(env_->scope()->kind() == Scope::GLOBAL);
   25.23 -            GlobalScope *globals = (GlobalScope *)env_->scope();
   25.24 -            if (!globals->addPublic(sym))
   25.25 -                return;
   25.26          }
   25.27  
   25.28          node->setSymbol(sym);
   25.29 @@ -298,9 +297,11 @@
   25.30  
   25.31          node->setScopes(argEnv.scope(), localEnv.scope());
   25.32      }
   25.33 +
   25.34      void visitStructureStatement(StructureStatement *node) {
   25.35          assert(false);
   25.36      }
   25.37 +
   25.38      void visiFunctionTypeStatementt(FunctionTypeStatement *node) {
   25.39          assert(false);
   25.40      }
   25.41 @@ -492,73 +493,23 @@
   25.42  static const int EVAL_ARRAY_SIZE = -1;
   25.43  static const int DYNAMIC_ARRAY_SIZE = -2;
   25.44  
   25.45 -class NameBinder : public AstVisitor
   25.46 +class NameBinderBase : public AstVisitor
   25.47  {
   25.48    public:
   25.49 -    class AutoLinkScope
   25.50 -    {
   25.51 -      public:
   25.52 -        AutoLinkScope(AutoLinkScope **prevp, Scope *scope)
   25.53 -          : prevp_(prevp),
   25.54 -            prev_(*prevp),
   25.55 -            scope_(scope)
   25.56 -        {
   25.57 -            if (scope_) {
   25.58 -                *prevp_ = this;
   25.59 -                if (prev_)
   25.60 -                    scope_->setParent(prev_->scope());
   25.61 -            }
   25.62 -        }
   25.63 -        ~AutoLinkScope() {
   25.64 -            if (scope_) {
   25.65 -                assert(*prevp_ == this);
   25.66 -                *prevp_ = prev_;
   25.67 -            }
   25.68 -        }
   25.69 -        Scope *scope() const {
   25.70 -            return scope_;
   25.71 -        }
   25.72 -
   25.73 -      private:
   25.74 -        AutoLinkScope **prevp_;
   25.75 -        AutoLinkScope *prev_;
   25.76 -        Scope *scope_;
   25.77 -    };
   25.78 -
   25.79 -  public:
   25.80 -    NameBinder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
   25.81 +    NameBinderBase(Zone *zone, CompileContext &cc, TranslationUnit *unit)
   25.82        : zone_(zone),
   25.83          pool_(zone->pool()),
   25.84          cc_(cc),
   25.85 -        unit_(unit),
   25.86 -        link_(NULL)
   25.87 +        unit_(unit)
   25.88      {
   25.89      }
   25.90  
   25.91 -    void bind() {
   25.92 -        // Start with the import scope, and collect all imported names.
   25.93 -        AutoLinkScope importScope(&link_, unit_->importScope());
   25.94  
   25.95 -        for (size_t i = 0; i < unit_->tree()->imports()->length(); i++)
   25.96 -            unit_->tree()->imports()->at(i)->accept(this);
   25.97 -
   25.98 -        // Next, enter the global scope and walk all statements.
   25.99 -        AutoLinkScope globalScope(&link_, unit_->globalScope());
  25.100 -        for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
  25.101 -            Statement *stmt = unit_->tree()->statements()->at(i);
  25.102 -            stmt->accept(this);
  25.103 -        }
  25.104 -    }
  25.105 -
  25.106 -    void visitVariableDeclaration(VariableDeclaration *node) {
  25.107 -        // Bind the initializer before registering the declaration, so that we
  25.108 -        // can error on bogus initializers (new x = x).
  25.109 -        if (node->initialization())
  25.110 -            node->initialization()->accept(this);
  25.111 -
  25.112 +  protected:
  25.113 +    Type *buildVariableType(VariableDeclaration *node) {
  25.114          Local<Type> type(zone_, bindType(node->type(), node->quals()));
  25.115          if (!type)
  25.116 -            return;
  25.117 +            return NULL;
  25.118  
  25.119          // We don't allow array typedefs yet.
  25.120          assert(!type->isArray());
  25.121 @@ -567,7 +518,7 @@
  25.122              int dims[MAX_ARRAY_DEPTH];
  25.123              int levels = evaluateDimensions(node->pos(), type, node->dims(), dims);
  25.124              if (levels < 0)
  25.125 -                return;
  25.126 +                return NULL;
  25.127  
  25.128              // Do some extra inference based on the initializer, if present.
  25.129              Expression *init = node->initialization();
  25.130 @@ -577,7 +528,7 @@
  25.131                                                   ? ArrayType::cast(type)->contained()
  25.132                                                   : type);
  25.133                      if (!inferFixedArrayDimensions(init->toArrayLiteral(), contained, dims, levels))
  25.134 -                        return;
  25.135 +                        return NULL;
  25.136                  } else if (init->isStringLiteral()) {
  25.137                      dims[levels - 1] = init->toStringLiteral()->string()->length() + 1;
  25.138                  }
  25.139 @@ -586,180 +537,13 @@
  25.140              // If we got extra dimensions, we need to build a new type.
  25.141              if (node->dims()) {
  25.142                  if ((type = buildArrayType(type, node->quals(), dims, node->dims()->length())) == NULL)
  25.143 -                    return;
  25.144 +                    return NULL;
  25.145              }
  25.146          }
  25.147  
  25.148 -        // If we're in global scope, and we received a |const| qualifier, then
  25.149 -        // we extend this to array references as well. This is to sort of mimic
  25.150 -        // SP1 functionality, but also means that you cannot have changeable
  25.151 -        // const pointers in global scope.
  25.152 -        if ((node->quals() & TypeQual_Const) &&
  25.153 -            type->isArray() &&
  25.154 -            link_->scope()->kind() == Scope::GLOBAL)
  25.155 -        {
  25.156 -            if ((type = zone_->types()->qualify(type, TypeQual_Const)) == NULL)
  25.157 -                return;
  25.158 -        }
  25.159 -
  25.160 -        // If the node already has a symbol (meaning it was a global), then
  25.161 -        // we don't have to do anything more.
  25.162 -        if (node->sym()) {
  25.163 -            assert(node->sym()->scope()->kind() == Scope::GLOBAL);
  25.164 -            node->sym()->setType(type);
  25.165 -            return;
  25.166 -        }
  25.167 -
  25.168 -        VariableSymbol *sym = new (pool_) VariableSymbol(link_->scope(), node->name(), node->pos(), type);
  25.169 -        node->setSymbol(sym);
  25.170 -       
  25.171 -        if (Symbol *other = link_->scope()->localLookup(sym->name())) {
  25.172 -            // Report, but allow errors to continue.
  25.173 -            cc_.reportError(sym->pos(), Message_RedeclaredName,
  25.174 -                            sym->name()->chars(),
  25.175 -                            other->pos().line,
  25.176 -                            other->pos().col);
  25.177 -            return;
  25.178 -        }
  25.179 -        
  25.180 -        link_->scope()->addSymbol(sym);
  25.181 -    }
  25.182 -    void visitEnumStatement(EnumStatement *node) {
  25.183 -    }
  25.184 -    void visitFunctionStatement(FunctionStatement *node) {
  25.185 -        AutoLinkScope argScope(&link_, node->argScope());
  25.186 -        AutoLinkScope varScope(&link_, node->varScope());
  25.187 -
  25.188 -        Local<FunctionType> type(zone_, node->sym()->type());
  25.189 -        if (!fillFunctionType(type, node->signature()))
  25.190 -            return;
  25.191 -
  25.192 -        if (node->body())
  25.193 -            node->body()->accept(this);
  25.194 -    }
  25.195 -    void visitStructureStatement(StructureStatement *node) {
  25.196 -        assert(false);
  25.197 -    }
  25.198 -    void visitFunctionTypeStatement(FunctionTypeStatement *node) {
  25.199 -        assert(false);
  25.200 +        return type;
  25.201      }
  25.202  
  25.203 -    void visitNameProxy(NameProxy *proxy) {
  25.204 -        Scope *scope = link_->scope();
  25.205 -        Symbol *sym = scope->lookup(proxy->name());
  25.206 -        if (!sym)
  25.207 -            cc_.reportError(proxy->pos(), Message_IdentifierNotFound, proxy->name()->chars());
  25.208 -        proxy->bind(sym);
  25.209 -    }
  25.210 -    void visitAssignment(Assignment *node) {
  25.211 -        node->lvalue()->accept(this);
  25.212 -        node->expression()->accept(this);
  25.213 -    }
  25.214 -    void visitBinaryExpression(BinaryExpression *node) {
  25.215 -        node->left()->accept(this);
  25.216 -        node->right()->accept(this);
  25.217 -    }
  25.218 -    void visitReturnStatement(ReturnStatement *node) {
  25.219 -        node->expression()->accept(this);
  25.220 -    }
  25.221 -    void visitForStatement(ForStatement *node) {
  25.222 -        AutoLinkScope scope(&link_, node->scope());
  25.223 -
  25.224 -        if (node->initialization())
  25.225 -            node->initialization()->accept(this);
  25.226 -        if (node->condition())
  25.227 -            node->condition()->accept(this);
  25.228 -        if (node->update())
  25.229 -            node->update()->accept(this);
  25.230 -        node->body()->accept(this);
  25.231 -    }
  25.232 -    void visitBlockStatement(BlockStatement *node) {
  25.233 -        AutoLinkScope scope(&link_, node->scope());
  25.234 -        for (size_t i = 0; i < node->statements()->length(); i++)
  25.235 -            node->statements()->at(i)->accept(this);
  25.236 -    }
  25.237 -    void visitIntegerLiteral(IntegerLiteral *node) {
  25.238 -    }
  25.239 -    void visitExpressionStatement(ExpressionStatement *node) {
  25.240 -        node->expression()->accept(this);
  25.241 -    }
  25.242 -    void visitCallExpression(CallExpression *node) {
  25.243 -        node->callee()->accept(this);
  25.244 -        for (size_t i = 0; i < node->arguments()->length(); i++)
  25.245 -            node->arguments()->at(i)->accept(this);
  25.246 -    }
  25.247 -    void visitIfStatement(IfStatement *node) {
  25.248 -        node->condition()->accept(this);
  25.249 -        node->ifTrue()->accept(this);
  25.250 -        if (node->ifFalse())
  25.251 -            node->ifFalse()->accept(this);
  25.252 -    }
  25.253 -    void visitIndexExpression(IndexExpression *node) {
  25.254 -        node->left()->accept(this);
  25.255 -        node->right()->accept(this);
  25.256 -    }
  25.257 -    void visitFloatLiteral(FloatLiteral *node) {
  25.258 -    }
  25.259 -    void visitWhileStatement(WhileStatement *node) {
  25.260 -        node->condition()->accept(this);
  25.261 -        node->body()->accept(this);
  25.262 -    }
  25.263 -    void visitBreakStatement(BreakStatement *node) {
  25.264 -    }
  25.265 -    void visitContinueStatement(ContinueStatement *node) {
  25.266 -    }
  25.267 -    void visitStringLiteral(StringLiteral *node) {
  25.268 -    }
  25.269 -    void visitIncDecExpression(IncDecExpression *node) {
  25.270 -        node->expression()->accept(this);
  25.271 -    }
  25.272 -    void visitUnaryExpression(UnaryExpression *node) {
  25.273 -        if (node->tag())
  25.274 -            node->tag()->accept(this);
  25.275 -        node->expression()->accept(this);
  25.276 -    }
  25.277 -    void visitTernaryExpression(TernaryExpression *node) {
  25.278 -        node->condition()->accept(this);
  25.279 -        node->left()->accept(this);
  25.280 -        node->right()->accept(this);
  25.281 -    }
  25.282 -    void visitBooleanLiteral(BooleanLiteral *node) {
  25.283 -    }
  25.284 -    void visitFieldExpression(FieldExpression *node) {
  25.285 -        node->left()->accept(this);
  25.286 -    }
  25.287 -    void visitSwitchStatement(SwitchStatement *node) {
  25.288 -        node->expression()->accept(this);
  25.289 -        node->defaultCase()->accept(this);
  25.290 -        for (size_t i = 0; i < node->cases()->length(); i++) {
  25.291 -            // We don't test case expressions because they are literals.
  25.292 -            Case *c = node->cases()->at(i);
  25.293 -            c->statement()->accept(this);
  25.294 -        }
  25.295 -    }
  25.296 -    void visitArrayLiteral(ArrayLiteral *node) {
  25.297 -        for (size_t i = 0; i < node->expressions()->length(); i++)
  25.298 -            node->expressions()->at(i)->accept(this);
  25.299 -    }
  25.300 -    void visitImportStatement(ImportStatement *node) {
  25.301 -        if (node->suffix() == TOK_STAR) {
  25.302 -            // Import every name.
  25.303 -            assert(false);
  25.304 -        } else {
  25.305 -            assert(false);
  25.306 -#if 0
  25.307 -            GlobalScope *other = node->source()->globalScope();
  25.308 -            Symbol *sym = other->findPublic(node->name());
  25.309 -            if (!sym) {
  25.310 -                cc_.reportError(node->pos(), Message_CannotResolveImport, node->name()->chars());
  25.311 -                return;
  25.312 -            }
  25.313 -            link_->scope()->addSymbol(sym);
  25.314 -#endif
  25.315 -        }
  25.316 -    }
  25.317 -
  25.318 -  private:
  25.319      int evaluateDimensions(const SourcePosition &pos, Handle<Type> typeArg, ExpressionList *exprs, int dims[MAX_ARRAY_DEPTH]) {
  25.320          unsigned level = 0;
  25.321          Local<Type> type(zone_, typeArg);
  25.322 @@ -967,11 +751,344 @@
  25.323          return zone_->types()->qualify(type, quals);
  25.324      }
  25.325  
  25.326 -  private:
  25.327 +  protected:
  25.328      Zone *zone_;
  25.329      PoolAllocator &pool_;
  25.330      CompileContext &cc_;
  25.331      TranslationUnit *unit_;
  25.332 +};
  25.333 +
  25.334 +class GlobalBuilder : public NameBinderBase
  25.335 +{
  25.336 +  public:
  25.337 +    GlobalBuilder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
  25.338 +      : NameBinderBase(zone, cc, unit)
  25.339 +    {
  25.340 +    }
  25.341 +
  25.342 +    Struct *build() {
  25.343 +        for (size_t i = 0; i < unit_->tree()->imports()->length(); i++)
  25.344 +            unit_->tree()->imports()->at(i)->accept(this);
  25.345 +
  25.346 +        // Next, enter the global scope and walk all statements.
  25.347 +        for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
  25.348 +            Statement *stmt = unit_->tree()->statements()->at(i);
  25.349 +            stmt->accept(this);
  25.350 +        }
  25.351 +
  25.352 +        Local<FixedArray> descs(zone_, FixedArray::New(zone_, descriptors_.length(), Heap::Tenure_Old));
  25.353 +        if (!descs)
  25.354 +            return NULL;
  25.355 +
  25.356 +        for (unsigned i = 0; i < descriptors_.length(); i++)
  25.357 +            descs->set(zone_, i, *descriptors_[i]);
  25.358 +
  25.359 +        Local<String> name(zone_, unit_->module()->name());
  25.360 +        Local<StructType> type(zone_, StructType::New(zone_, name, descs));
  25.361 +        if (!type)
  25.362 +            return NULL;
  25.363 +
  25.364 +        Local<StructMap> map(zone_, type->newMap());
  25.365 +        return Struct::New(zone_, map, Heap::Tenure_Old);
  25.366 +    }
  25.367 +
  25.368 +    void visitEnumStatement(EnumStatement *stmt) {
  25.369 +    }
  25.370 +
  25.371 +    void visitNameProxy(NameProxy *proxy) {
  25.372 +        // Don't report errors here, since we'll report them later.
  25.373 +        Scope *scope = unit_->globalScope();
  25.374 +        Symbol *sym = scope->lookup(proxy->name());
  25.375 +        proxy->bind(sym);
  25.376 +    }
  25.377 +
  25.378 +    void visitFunctionStatement(FunctionStatement *node) {
  25.379 +        Local<FunctionType> type(zone_, node->sym()->type());
  25.380 +        if (!fillFunctionType(type, node->signature()))
  25.381 +            return;
  25.382 +
  25.383 +        unsigned offset;
  25.384 +        if (!builder_.add(type, &offset))
  25.385 +            return;
  25.386 +
  25.387 +        Descriptor::Visibility visibility = (node->token() == TOK_NATIVE || node->token() == TOK_FORWARD)
  25.388 +                                            ? Descriptor::Public
  25.389 +                                            : Descriptor::Private;
  25.390 +
  25.391 +        Descriptor *desc = Descriptor::New(zone_, node->name(), type, visibility);
  25.392 +        if (!desc)
  25.393 +            return;
  25.394 +        if (!descriptors_.append(new (pool_) ScopedRoot<Descriptor>(desc)))
  25.395 +            return;
  25.396 +    }
  25.397 +
  25.398 +    void visitVariableDeclaration(VariableDeclaration *node) {
  25.399 +        Local<Type> type(zone_, buildVariableType(node));
  25.400 +        if (!type)
  25.401 +            return;
  25.402 +
  25.403 +        // If we're in global scope, and we received a |const| qualifier, then
  25.404 +        // we extend this to array references as well. This is to sort of mimic
  25.405 +        // SP1 functionality, but also means that you cannot have changeable
  25.406 +        // const pointers in global scope.
  25.407 +        if ((node->quals() & TypeQual_Const) && type->isArray()) {
  25.408 +            if ((type = zone_->types()->qualify(type, TypeQual_Const)) == NULL)
  25.409 +                return;
  25.410 +        }
  25.411 +
  25.412 +        node->sym()->setType(type);
  25.413 +
  25.414 +        unsigned offset;
  25.415 +        if (!builder_.add(type, &offset))
  25.416 +            return;
  25.417 +
  25.418 +        Descriptor *desc = Descriptor::New(zone_, node->name(), type, Descriptor::Private);
  25.419 +        if (!desc)
  25.420 +            return;
  25.421 +        if (!descriptors_.append(new (pool_) ScopedRoot<Descriptor>(desc)))
  25.422 +            return;
  25.423 +    }
  25.424 +
  25.425 +    void visitImportStatement(ImportStatement *node) {
  25.426 +        // Eventually we'll handle |from| style imports as well.
  25.427 +        {
  25.428 +            PathComponent *path = node->path();
  25.429 +            while (path->next)
  25.430 +                path = path->next;
  25.431 +
  25.432 +            // Imports automatically go into the importScope. For now, we
  25.433 +            // error if there are any duplicate symbols entered into the
  25.434 +            // importScope.
  25.435 +            if (Symbol *sym = unit_->importScope()->localLookup(path->name)) {
  25.436 +                cc_.reportError(node->pos(), Message_DuplicateImport, path->name->chars());
  25.437 +                return;
  25.438 +            }
  25.439 +
  25.440 +            Local<Type> type(zone_, zone_->types()->getImportable());
  25.441 +            ImportSymbol *sym = new (pool_) ImportSymbol(unit_->importScope(), path->name, node->pos(), type, node->importIndex());
  25.442 +            if (!unit_->importScope()->addSymbol(sym))
  25.443 +                return;
  25.444 +        }
  25.445 +    }
  25.446 +
  25.447 +  private:
  25.448 +    StructureBufferBuilder builder_;
  25.449 +    Vector<ScopedRoot<Descriptor> *> descriptors_;
  25.450 +};
  25.451 +    
  25.452 +class NameBinder : public NameBinderBase
  25.453 +{
  25.454 +  public:
  25.455 +    class AutoLinkScope
  25.456 +    {
  25.457 +      public:
  25.458 +        AutoLinkScope(AutoLinkScope **prevp, Scope *scope)
  25.459 +          : prevp_(prevp),
  25.460 +            prev_(*prevp),
  25.461 +            scope_(scope)
  25.462 +        {
  25.463 +            if (scope_) {
  25.464 +                *prevp_ = this;
  25.465 +                if (prev_)
  25.466 +                    scope_->setParent(prev_->scope());
  25.467 +            }
  25.468 +        }
  25.469 +        ~AutoLinkScope() {
  25.470 +            if (scope_) {
  25.471 +                assert(*prevp_ == this);
  25.472 +                *prevp_ = prev_;
  25.473 +            }
  25.474 +        }
  25.475 +        Scope *scope() const {
  25.476 +            return scope_;
  25.477 +        }
  25.478 +
  25.479 +      private:
  25.480 +        AutoLinkScope **prevp_;
  25.481 +        AutoLinkScope *prev_;
  25.482 +        Scope *scope_;
  25.483 +    };
  25.484 +
  25.485 +  public:
  25.486 +    NameBinder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
  25.487 +      : NameBinderBase(zone, cc, unit),
  25.488 +        link_(NULL)
  25.489 +    {
  25.490 +    }
  25.491 +
  25.492 +    void bind() {
  25.493 +        // Start with the import scope, and collect all imported names.
  25.494 +        AutoLinkScope importScope(&link_, unit_->importScope());
  25.495 +
  25.496 +        for (size_t i = 0; i < unit_->tree()->imports()->length(); i++)
  25.497 +            unit_->tree()->imports()->at(i)->accept(this);
  25.498 +
  25.499 +        // Next, enter the global scope and walk all statements.
  25.500 +        AutoLinkScope globalScope(&link_, unit_->globalScope());
  25.501 +        for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
  25.502 +            Statement *stmt = unit_->tree()->statements()->at(i);
  25.503 +            stmt->accept(this);
  25.504 +        }
  25.505 +    }
  25.506 +
  25.507 +    void visitVariableDeclaration(VariableDeclaration *node) {
  25.508 +        // Bind the initializer before registering the declaration, so that we
  25.509 +        // can error on bogus initializers (new x = x).
  25.510 +        if (node->initialization())
  25.511 +            node->initialization()->accept(this);
  25.512 +
  25.513 +        // If the node already has a symbol (meaning it was a global), then
  25.514 +        // we don't have to do anything more.
  25.515 +        if (node->sym())
  25.516 +            return;
  25.517 +
  25.518 +        Local<Type> type(zone_, buildVariableType(node));
  25.519 +        if (!type)
  25.520 +            return;
  25.521 +
  25.522 +        VariableSymbol *sym = new (pool_) VariableSymbol(link_->scope(), node->name(), node->pos(), type);
  25.523 +        node->setSymbol(sym);
  25.524 +       
  25.525 +        if (Symbol *other = link_->scope()->localLookup(sym->name())) {
  25.526 +            // Report, but allow errors to continue.
  25.527 +            cc_.reportError(sym->pos(), Message_RedeclaredName,
  25.528 +                            sym->name()->chars(),
  25.529 +                            other->pos().line,
  25.530 +                            other->pos().col);
  25.531 +            return;
  25.532 +        }
  25.533 +        
  25.534 +        link_->scope()->addSymbol(sym);
  25.535 +    }
  25.536 +    void visitEnumStatement(EnumStatement *node) {
  25.537 +    }
  25.538 +    void visitFunctionStatement(FunctionStatement *node) {
  25.539 +        AutoLinkScope argScope(&link_, node->argScope());
  25.540 +        AutoLinkScope varScope(&link_, node->varScope());
  25.541 +
  25.542 +        // If the function is in the global scope, we've already computed its
  25.543 +        // type.
  25.544 +        if (node->sym()->scope()->kind() != Scope::GLOBAL) {
  25.545 +            Local<FunctionType> type(zone_, node->sym()->type());
  25.546 +            if (!fillFunctionType(type, node->signature()))
  25.547 +                return;
  25.548 +        }
  25.549 +
  25.550 +        if (node->body())
  25.551 +            node->body()->accept(this);
  25.552 +    }
  25.553 +    void visitStructureStatement(StructureStatement *node) {
  25.554 +        assert(false);
  25.555 +    }
  25.556 +    void visitFunctionTypeStatement(FunctionTypeStatement *node) {
  25.557 +        assert(false);
  25.558 +    }
  25.559 +
  25.560 +    void visitNameProxy(NameProxy *proxy) {
  25.561 +        // We could have already bound globals.
  25.562 +        if (proxy->sym())
  25.563 +            return;
  25.564 +
  25.565 +        Scope *scope = link_->scope();
  25.566 +        Symbol *sym = scope->lookup(proxy->name());
  25.567 +        if (!sym)
  25.568 +            cc_.reportError(proxy->pos(), Message_IdentifierNotFound, proxy->name()->chars());
  25.569 +        proxy->bind(sym);
  25.570 +    }
  25.571 +    void visitAssignment(Assignment *node) {
  25.572 +        node->lvalue()->accept(this);
  25.573 +        node->expression()->accept(this);
  25.574 +    }
  25.575 +    void visitBinaryExpression(BinaryExpression *node) {
  25.576 +        node->left()->accept(this);
  25.577 +        node->right()->accept(this);
  25.578 +    }
  25.579 +    void visitReturnStatement(ReturnStatement *node) {
  25.580 +        node->expression()->accept(this);
  25.581 +    }
  25.582 +    void visitForStatement(ForStatement *node) {
  25.583 +        AutoLinkScope scope(&link_, node->scope());
  25.584 +
  25.585 +        if (node->initialization())
  25.586 +            node->initialization()->accept(this);
  25.587 +        if (node->condition())
  25.588 +            node->condition()->accept(this);
  25.589 +        if (node->update())
  25.590 +            node->update()->accept(this);
  25.591 +        node->body()->accept(this);
  25.592 +    }
  25.593 +    void visitBlockStatement(BlockStatement *node) {
  25.594 +        AutoLinkScope scope(&link_, node->scope());
  25.595 +        for (size_t i = 0; i < node->statements()->length(); i++)
  25.596 +            node->statements()->at(i)->accept(this);
  25.597 +    }
  25.598 +    void visitIntegerLiteral(IntegerLiteral *node) {
  25.599 +    }
  25.600 +    void visitExpressionStatement(ExpressionStatement *node) {
  25.601 +        node->expression()->accept(this);
  25.602 +    }
  25.603 +    void visitCallExpression(CallExpression *node) {
  25.604 +        node->callee()->accept(this);
  25.605 +        for (size_t i = 0; i < node->arguments()->length(); i++)
  25.606 +            node->arguments()->at(i)->accept(this);
  25.607 +    }
  25.608 +    void visitIfStatement(IfStatement *node) {
  25.609 +        node->condition()->accept(this);
  25.610 +        node->ifTrue()->accept(this);
  25.611 +        if (node->ifFalse())
  25.612 +            node->ifFalse()->accept(this);
  25.613 +    }
  25.614 +    void visitIndexExpression(IndexExpression *node) {
  25.615 +        node->left()->accept(this);
  25.616 +        node->right()->accept(this);
  25.617 +    }
  25.618 +    void visitFloatLiteral(FloatLiteral *node) {
  25.619 +    }
  25.620 +    void visitWhileStatement(WhileStatement *node) {
  25.621 +        node->condition()->accept(this);
  25.622 +        node->body()->accept(this);
  25.623 +    }
  25.624 +    void visitBreakStatement(BreakStatement *node) {
  25.625 +    }
  25.626 +    void visitContinueStatement(ContinueStatement *node) {
  25.627 +    }
  25.628 +    void visitStringLiteral(StringLiteral *node) {
  25.629 +    }
  25.630 +    void visitIncDecExpression(IncDecExpression *node) {
  25.631 +        node->expression()->accept(this);
  25.632 +    }
  25.633 +    void visitUnaryExpression(UnaryExpression *node) {
  25.634 +        if (node->tag())
  25.635 +            node->tag()->accept(this);
  25.636 +        node->expression()->accept(this);
  25.637 +    }
  25.638 +    void visitTernaryExpression(TernaryExpression *node) {
  25.639 +        node->condition()->accept(this);
  25.640 +        node->left()->accept(this);
  25.641 +        node->right()->accept(this);
  25.642 +    }
  25.643 +    void visitBooleanLiteral(BooleanLiteral *node) {
  25.644 +    }
  25.645 +    void visitFieldExpression(FieldExpression *node) {
  25.646 +        node->left()->accept(this);
  25.647 +    }
  25.648 +    void visitSwitchStatement(SwitchStatement *node) {
  25.649 +        node->expression()->accept(this);
  25.650 +        node->defaultCase()->accept(this);
  25.651 +        for (size_t i = 0; i < node->cases()->length(); i++) {
  25.652 +            // We don't test case expressions because they are literals.
  25.653 +            Case *c = node->cases()->at(i);
  25.654 +            c->statement()->accept(this);
  25.655 +        }
  25.656 +    }
  25.657 +    void visitArrayLiteral(ArrayLiteral *node) {
  25.658 +        for (size_t i = 0; i < node->expressions()->length(); i++)
  25.659 +            node->expressions()->at(i)->accept(this);
  25.660 +    }
  25.661 +    void visitImportStatement(ImportStatement *node) {
  25.662 +    }
  25.663 +
  25.664 +  private:
  25.665      AutoLinkScope *link_;
  25.666  };
  25.667  
  25.668 @@ -979,6 +1096,18 @@
  25.669  ke::BindNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
  25.670  {
  25.671      AutoEnterCompileContext enter(cc, unit);
  25.672 +
  25.673 +    // Because of the way globals work in Pawn, we need a precursor step to
  25.674 +    // actually enter global symbols into the global struct. They're already
  25.675 +    // in the global symbol table, so we know they won't clash. This process
  25.676 +    // also binds any remaining types on global variables.
  25.677 +    GlobalBuilder builder(zone, cc, unit);
  25.678 +    Local<Struct> globals(zone, builder.build());
  25.679 +    if (!globals || unit->failed())
  25.680 +        return;
  25.681 +
  25.682 +    unit->module()->setGlobals(globals);
  25.683 +
  25.684      NameBinder binder(zone, cc, unit);
  25.685      binder.bind();
  25.686  }
    26.1 --- a/src/compiler/Parser.cpp	Tue Jan 01 20:08:34 2013 -0800
    26.2 +++ b/src/compiler/Parser.cpp	Sun Jan 06 13:52:21 2013 -0800
    26.3 @@ -1236,9 +1236,7 @@
    26.4  static inline ScopedRoot<T> *
    26.5  NewScopedRoot(PoolAllocator &pool, Handle<T> obj)
    26.6  {
    26.7 -    ScopedRoot<T> *root = pool.alloc<ScopedRoot<T> >();
    26.8 -    new (root) ScopedRoot<T>(obj);
    26.9 -    return root;
   26.10 +    return new (pool) ScopedRoot<T>(obj);
   26.11  }
   26.12  
   26.13  ImportStatement *
   26.14 @@ -1246,7 +1244,7 @@
   26.15  {
   26.16      SourcePosition pos = scanner_.begin();
   26.17  
   26.18 -    // import       ::= import_path ("." "*")?
   26.19 +    // import       ::= import_path
   26.20      // import_path  ::= name |
   26.21      //                  name "." import_path
   26.22  
   26.23 @@ -1259,11 +1257,6 @@
   26.24  
   26.25      TokenKind suffix = TOK_NONE;
   26.26      while (match(TOK_DOT)) {
   26.27 -        if (match(TOK_STAR)) {
   26.28 -            suffix = TOK_STAR;
   26.29 -            break;
   26.30 -        }
   26.31 -
   26.32          if ((name = expectName()) == NULL)
   26.33              return NULL;
   26.34  
   26.35 @@ -1271,7 +1264,7 @@
   26.36          current = current->next;
   26.37      }
   26.38  
   26.39 -    return new (pool_) ImportStatement(pos, root, suffix);
   26.40 +    return new (pool_) ImportStatement(pos, root);
   26.41  }
   26.42  
   26.43  Statement *
    27.1 --- a/src/compiler/Scopes.cpp	Tue Jan 01 20:08:34 2013 -0800
    27.2 +++ b/src/compiler/Scopes.cpp	Sun Jan 06 13:52:21 2013 -0800
    27.3 @@ -168,47 +168,6 @@
    27.4      return scope;
    27.5  }
    27.6  
    27.7 -bool
    27.8 -GlobalScope::addPublic(Symbol *sym)
    27.9 -{
   27.10 -    return publics_.append(sym);
   27.11 -}
   27.12 -
   27.13 -Symbol *
   27.14 -GlobalScope::findPublic(Handle<String> name)
   27.15 -{
   27.16 -    for (size_t i = 0; i < publics_.length(); i++) {
   27.17 -        if (publics_[i]->name() == name)
   27.18 -            return publics_[i];
   27.19 -    }
   27.20 -    return NULL;
   27.21 -}
   27.22 -
   27.23 -Struct *
   27.24 -GlobalScope::build(Zone *zone)
   27.25 -{
   27.26 -    Local<FixedArray> descriptors(zone, FixedArray::New(zone, names_.length(), Heap::Tenure_Old));
   27.27 -
   27.28 -    for (size_t i = 0; i < names_.length(); i++) {
   27.29 -        Handle<String> name = names_[i]->name();
   27.30 -        Handle<Type> type = names_[i]->type();
   27.31 -        assert(type);
   27.32 -
   27.33 -        Local<Descriptor> desc(zone, Descriptor::New(zone, name, type));
   27.34 -        if (!desc)
   27.35 -            return NULL;
   27.36 -        
   27.37 -        descriptors->set(zone, i, desc);
   27.38 -    }
   27.39 -
   27.40 -    Local<StructType> type(zone, StructType::New(zone, Handle<String>::Null(), descriptors));
   27.41 -    if (!type)
   27.42 -        return NULL;
   27.43 -
   27.44 -    Local<StructMap> map(zone, type->newMap());
   27.45 -    return Struct::New(zone, map, Heap::Tenure_Old);
   27.46 -}
   27.47 -
   27.48  ImportScope::ImportScope(PoolAllocator &pool)
   27.49    : Scope(pool, Scope::IMPORT, NULL)
   27.50  {
    28.1 --- a/src/compiler/Scopes.h	Tue Jan 01 20:08:34 2013 -0800
    28.2 +++ b/src/compiler/Scopes.h	Sun Jan 06 13:52:21 2013 -0800
    28.3 @@ -101,15 +101,8 @@
    28.4    public:
    28.5      static GlobalScope *New(PoolAllocator &pool, ImportScope *parent);
    28.6  
    28.7 -    bool addPublic(Symbol *symbol);
    28.8 -    Symbol *findPublic(Handle<String> name);
    28.9 -    Struct *build(Zone *zone);
   28.10 -
   28.11    private:
   28.12      GlobalScope(PoolAllocator &pool, ImportScope *parent);
   28.13 -
   28.14 -  private:
   28.15 -    PoolList<Symbol *> publics_;
   28.16  };
   28.17  
   28.18  class ImportScope : public Scope
    29.1 --- a/src/compiler/SemanticAnalysis.cpp	Tue Jan 01 20:08:34 2013 -0800
    29.2 +++ b/src/compiler/SemanticAnalysis.cpp	Sun Jan 06 13:52:21 2013 -0800
    29.3 @@ -93,11 +93,6 @@
    29.4          stmt->accept(this);
    29.5      }
    29.6  
    29.7 -    Local<Struct> globals(zone_, unit_->globalScope()->build(zone_));
    29.8 -    if (!globals)
    29.9 -        return;
   29.10 -    unit_->module()->setGlobals(globals);
   29.11 -
   29.12      Local<Code> code(zone_, __ finish());
   29.13      if (!code)
   29.14          return;
   29.15 @@ -448,7 +443,7 @@
   29.16              __ float_(0);
   29.17          } else if (type->isArray()) {
   29.18              Local<ArrayType> atype(zone_, ArrayType::cast(type));
   29.19 -            Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, atype));
   29.20 +            Local<ArrayMap> map(zone_, atype->newMap());
   29.21              if (!map)
   29.22                  return;
   29.23  
   29.24 @@ -570,6 +565,13 @@
   29.25      Symbol *sym = proxy->sym();
   29.26  
   29.27      switch (sym->kind()) {
   29.28 +      case Symbol::kImport:
   29.29 +      {
   29.30 +        ImportSymbol *import = sym->toImport();
   29.31 +        hir_ = new (pool_) HImport(proxy, sym->type(), import->index());
   29.32 +        break;
   29.33 +      }
   29.34 +
   29.35        case Symbol::kConstant:
   29.36        {
   29.37          ConstantSymbol *val = sym->toConstant();
   29.38 @@ -936,7 +938,7 @@
   29.39          // Transform the string literal into an array literal. We give it the
   29.40          // type of the left-hand side. The constness of the destination type
   29.41          // will determine whether HArray duplicates it or not.
   29.42 -        Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, actual));
   29.43 +        Local<ArrayMap> map(zone_, actual->newMap());
   29.44          if (!map)
   29.45              return NULL;
   29.46  
   29.47 @@ -1066,6 +1068,10 @@
   29.48  {
   29.49      Local<Type> from(zone_, hir->type());
   29.50  
   29.51 +    // If the source is *ever* an importable, we just fail.
   29.52 +    if (from->isImportable())
   29.53 +        return typeFailure(hir->node()->pos(), from, to);
   29.54 +
   29.55      if (from->isInt32() && to->isFloat())
   29.56          return new (pool_) HConvert(hir->node(), to, OP_CVT_I2F, hir);
   29.57      if (from->isInt32() && to->isBool())
   29.58 @@ -1218,6 +1224,70 @@
   29.59      }
   29.60  }
   29.61  
   29.62 +void
   29.63 +SemanticAnalysis::import(HIR *hir, FieldExpression *node)
   29.64 +{
   29.65 +    // Note that we don't care if the hir type is "importable", since we
   29.66 +    // can only do anything if the important has a constant binding.
   29.67 +    unsigned index = hir->toImport()->index();
   29.68 +    Local<Importable> importable(zone_, unit_->module()->getImportAt(index));
   29.69 +
   29.70 +    if (importable->isPackage()) {
   29.71 +        // Look at what's already loaded and see if anything exists. We
   29.72 +        // can't create stuff on-demand here since it's too late to add
   29.73 +        // new translation units to the CompileContext.
   29.74 +        Local<Package> package(zone_, Package::cast(importable));
   29.75 +        Local<Importable> found(zone_, package->import(node->field()));
   29.76 +        if (!found) {
   29.77 +            cc_.reportError(node->pos(), Message_PackageDoesNotHaveMember, node->field()->chars());
   29.78 +            return;
   29.79 +        }
   29.80 +
   29.81 +        // If we did find something, make sure it is in our import list.
   29.82 +        // If we didn't explicitly import it, we have no right to use it.
   29.83 +        for (index = 0; index < unit_->module()->imports(); index++) {
   29.84 +            if (unit_->module()->getImportAt(index) == importable)
   29.85 +                break;
   29.86 +        }
   29.87 +
   29.88 +        if (index == unit_->module()->imports()) {
   29.89 +            cc_.reportError(node->pos(), Message_ImportWasNeverImported, node->field()->chars());
   29.90 +            return;
   29.91 +        }
   29.92 +
   29.93 +        // Just create a new HImport.
   29.94 +        hir_ = new (pool_) HImport(node, hir->type(), index);
   29.95 +    } else {
   29.96 +        // Modules can never have sub-modules or sub-packages.
   29.97 +        unsigned index;
   29.98 +        Local<Module> module(zone_, Module::cast(importable));
   29.99 +        Local<StructMap> map(zone_, module->globals()->map());
  29.100 +        Local<Descriptor> desc(zone_, map->type()->lookupField(node->field(), &index));
  29.101 +        if (!desc) {
  29.102 +            cc_.reportError(node->pos(), Message_FieldNotFound, node->field()->chars());
  29.103 +            return;
  29.104 +        }
  29.105 +        hir_ = new (pool_) HField(node, hir, desc->type(), index);
  29.106 +    }
  29.107 +}
  29.108 +
  29.109 +void
  29.110 +SemanticAnalysis::visitFieldExpression(FieldExpression *node)
  29.111 +{
  29.112 +    HIR *hir = eval(node->left());
  29.113 +    if (!hir)
  29.114 +        return;
  29.115 +
  29.116 +    if (hir->isImport()) {
  29.117 +        import(hir, node);
  29.118 +        return;
  29.119 +    }
  29.120 +
  29.121 +    char name[255];
  29.122 +    cc_.reportError(node->pos(), Message_InvalidFieldExpression,
  29.123 +                    GetTypeName(hir->type(), name, sizeof(name)));
  29.124 +}
  29.125 +
  29.126  static inline TokenKind
  29.127  ToCompare(Expression *expr)
  29.128  {
    30.1 --- a/src/compiler/SemanticAnalysis.h	Tue Jan 01 20:08:34 2013 -0800
    30.2 +++ b/src/compiler/SemanticAnalysis.h	Sun Jan 06 13:52:21 2013 -0800
    30.3 @@ -67,6 +67,7 @@
    30.4      void visitStringLiteral(StringLiteral *node);
    30.5      void visitUnaryExpression(UnaryExpression *node);
    30.6      void visitBooleanLiteral(BooleanLiteral *node);
    30.7 +    void visitFieldExpression(FieldExpression *node);
    30.8  #if 0
    30.9      void visitFunctionTypeStatement(FunctionTypeStatement *node);
   30.10      void visitImportStatement(ImportStatement *node);
   30.11 @@ -74,12 +75,12 @@
   30.12      void visitSwitchStatement(SwitchStatement *node);
   30.13  
   30.14      void visitTernaryExpression(TernaryExpression *node);
   30.15 -    void visitFieldExpression(FieldExpression *node);
   30.16      void visitArrayLiteral(ArrayLiteral *node);
   30.17  #endif
   30.18  
   30.19    private:
   30.20      bool checkArgumentCount(Handle<FunctionType> type, unsigned actual);
   30.21 +    void import(HIR *hir, FieldExpression *node);
   30.22  
   30.23    private:
   30.24      enum CoercionKind {
    31.1 --- a/src/compiler/Symbols.h	Tue Jan 01 20:08:34 2013 -0800
    31.2 +++ b/src/compiler/Symbols.h	Sun Jan 06 13:52:21 2013 -0800
    31.3 @@ -38,8 +38,8 @@
    31.4      _(Constant)         \
    31.5      /* A named type (class struct, typedef, etc) produces a TypeSymbol. */ \
    31.6      _(Type)             \
    31.7 -    /* // A module import produces a ModuleSymbol. */   \
    31.8 -    _(Module)
    31.9 +    /* An import name. */ \
   31.10 +    _(Import)
   31.11  
   31.12  #define _(name)     class name##Symbol;
   31.13  SYMBOL_KINDS(_)
   31.14 @@ -208,6 +208,28 @@
   31.15      BoxedPrimitive value_;
   31.16  };
   31.17  
   31.18 +class ImportSymbol : public Symbol
   31.19 +{
   31.20 +  public:
   31.21 +    ImportSymbol(Scope *scope, Handle<String> name, const SourcePosition &pos, Handle<Type> type,
   31.22 +                 unsigned index)
   31.23 +      : Symbol(scope, name, pos),
   31.24 +        index_(index)
   31.25 +    {
   31.26 +        type_ = type;
   31.27 +    }
   31.28 +
   31.29 +    Kind kind() const {
   31.30 +        return kImport;
   31.31 +    }
   31.32 +    unsigned index() const {
   31.33 +        return index_;
   31.34 +    }
   31.35 +
   31.36 +  private:
   31.37 +      unsigned index_;
   31.38 +};
   31.39 +
   31.40  }
   31.41  
   31.42  #endif // _include_sp2_symbol_h_
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/tests/basic/import-sysroot-select.out	Sun Jan 06 13:52:21 2013 -0800
    32.3 @@ -0,0 +1,1 @@
    32.4 +5 is 5.000000
    33.1 --- a/tests/basic/import-sysroot-select.sp	Tue Jan 01 20:08:34 2013 -0800
    33.2 +++ b/tests/basic/import-sysroot-select.sp	Sun Jan 06 13:52:21 2013 -0800
    33.3 @@ -1,5 +1,3 @@
    33.4 -import shell;
    33.5 -import shell;
    33.6  import shell;
    33.7  
    33.8  public main()
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/tests/basic/shell.sp	Sun Jan 06 13:52:21 2013 -0800
    34.3 @@ -0,0 +1,3 @@
    34.4 +native PrintNum(num);
    34.5 +native PrintString(const char:text[]);
    34.6 +native PrintFloat(float:f);
    35.1 --- a/tests/shell.sp	Tue Jan 01 20:08:34 2013 -0800
    35.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.3 @@ -1,5 +0,0 @@
    35.4 -native PrintNum(num);
    35.5 -
    35.6 -native PrintString(const char:text[]);
    35.7 -
    35.8 -native PrintFloat(float:f);