Implement |from x import *| syntax for modules.
authorDavid Anderson <dvander@alliedmods.net>
Sat Jan 12 16:13:46 2013 -0800 (2013-01-12)
changeset 258241d082d6d89
parent 257 9db4cc815ebc
child 259 99ab8b19f0b9
Implement |from x import *| syntax for modules.
src/FixedArray.cpp
src/Messages.tbl
src/Reference.h
src/Types.cpp
src/Types.h
src/compiler/AST.h
src/compiler/CompileContext.cpp
src/compiler/NameBinding.cpp
src/compiler/NameBinding.h
src/compiler/Parser.cpp
src/compiler/Parser.h
src/compiler/Scanner.cpp
src/compiler/Scopes.h
src/compiler/SemanticAnalysis.cpp
src/compiler/Symbols.h
src/compiler/Token.h
tests/basic/import-sysroot-all.out
tests/basic/import-sysroot-all.sp
tests/basic/import-sysroot-module.out
tests/basic/import-sysroot-module.sp
tests/basic/import-sysroot-select.out
tests/basic/import-sysroot-select.sp
     1.1 --- a/src/FixedArray.cpp	Sun Jan 06 13:56:56 2013 -0800
     1.2 +++ b/src/FixedArray.cpp	Sat Jan 12 16:13:46 2013 -0800
     1.3 @@ -1,19 +1,19 @@
     1.4  /*
     1.5   * Copyright (C) 2012 David Anderson
     1.6   *
     1.7 - * This file is part of JITCraft.
     1.8 + * This file is part of SourcePawn.
     1.9   *
    1.10 - * JITCraft is free software: you can redistribute it and/or modify it under
    1.11 + * SourcePawn is free software: you can redistribute it and/or modify it under
    1.12   * the terms of the GNU General Public License as published by the Free
    1.13   * Software Foundation, either version 3 of the License, or (at your option)
    1.14   * any later version.
    1.15   * 
    1.16 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    1.17 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    1.18   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    1.19   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    1.20   *
    1.21   * You should have received a copy of the GNU General Public License along with
    1.22 - * JITCraft. If not, see http://www.gnu.org/licenses/.
    1.23 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
    1.24   */
    1.25  #include <limits.h>
    1.26  #include <string.h>
     2.1 --- a/src/Messages.tbl	Sun Jan 06 13:56:56 2013 -0800
     2.2 +++ b/src/Messages.tbl	Sat Jan 12 16:13:46 2013 -0800
     2.3 @@ -90,4 +90,5 @@
     2.4  MSG(InvalidFieldExpression,			TypeError,				"type '%s' does not have any fields")
     2.5  MSG(PackageDoesNotHaveMember,		TypeError,				"package does not have member '%s' (check imports)")
     2.6  MSG(ImportWasNeverImported,         TypeError,              "'%s' was never imported")
     2.7 -MSG(FieldNotFound,                  TypeError,              "field '%s' not found")
     2.8 \ No newline at end of file
     2.9 +MSG(FieldNotFound,                  TypeError,              "field '%s' not found")
    2.10 +MSG(BadImportFrom,					TypeError,              "expected '*' or <name>")
    2.11 \ No newline at end of file
     3.1 --- a/src/Reference.h	Sun Jan 06 13:56:56 2013 -0800
     3.2 +++ b/src/Reference.h	Sat Jan 12 16:13:46 2013 -0800
     3.3 @@ -1,19 +1,19 @@
     3.4  /*
     3.5   * Copyright (C) 2012 David Anderson
     3.6   *
     3.7 - * This file is part of JITCraft.
     3.8 + * This file is part of SourcePawn.
     3.9   *
    3.10 - * JITCraft is free software: you can redistribute it and/or modify it under
    3.11 + * SourcePawn is free software: you can redistribute it and/or modify it under
    3.12   * the terms of the GNU General Public License as published by the Free
    3.13   * Software Foundation, either version 3 of the License, or (at your option)
    3.14   * any later version.
    3.15   * 
    3.16 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    3.17 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    3.18   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    3.19   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    3.20   *
    3.21   * You should have received a copy of the GNU General Public License along with
    3.22 - * JITCraft. If not, see http://www.gnu.org/licenses/.
    3.23 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
    3.24   */
    3.25  #ifndef _include_jitcraft_reference_h_
    3.26  #define _include_jitcraft_reference_h_
     4.1 --- a/src/Types.cpp	Sun Jan 06 13:56:56 2013 -0800
     4.2 +++ b/src/Types.cpp	Sat Jan 12 16:13:46 2013 -0800
     4.3 @@ -205,8 +205,9 @@
     4.4  }
     4.5  
     4.6  Descriptor *
     4.7 -StructType::lookupField(Handle<String> name, unsigned *index)
     4.8 +StructType::lookupField(String *name, unsigned *index)
     4.9  {
    4.10 +    // :TODO: assert no GC
    4.11      for (unsigned i = 0; i < fields_->length(); i++) {
    4.12          Descriptor *desc = Descriptor::cast(fields_->at(i));
    4.13          if (desc->name() == name) {
     5.1 --- a/src/Types.h	Sun Jan 06 13:56:56 2013 -0800
     5.2 +++ b/src/Types.h	Sat Jan 12 16:13:46 2013 -0800
     5.3 @@ -377,7 +377,7 @@
     5.4          assert(isStruct());
     5.5          return fields_;
     5.6      }
     5.7 -    Descriptor *lookupField(Handle<String> name, unsigned *index = NULL);
     5.8 +    Descriptor *lookupField(String *name, unsigned *index = NULL);
     5.9  
    5.10      // Objects of this type can be created with this cached map.
    5.11      StructMap *newMap() {
     6.1 --- a/src/compiler/AST.h	Sun Jan 06 13:56:56 2013 -0800
     6.2 +++ b/src/compiler/AST.h	Sat Jan 12 16:13:46 2013 -0800
     6.3 @@ -1086,9 +1086,10 @@
     6.4  class ImportStatement : public Statement
     6.5  {
     6.6    public:
     6.7 -    ImportStatement(const SourcePosition &pos, PathComponent *path)
     6.8 +    ImportStatement(const SourcePosition &pos, PathComponent *path, NameList *names)
     6.9        : Statement(pos),
    6.10 -        path_(path)
    6.11 +        path_(path),
    6.12 +        names_(names)
    6.13      {
    6.14      }
    6.15  
    6.16 @@ -1103,17 +1104,25 @@
    6.17      Handle<Importable> source() {
    6.18          return source_;
    6.19      }
    6.20 -    unsigned importIndex() {
    6.21 +    unsigned importIndex() const {
    6.22          return importIndex_;
    6.23      }
    6.24      void setImportIndex(unsigned index) {
    6.25          importIndex_ = index;
    6.26      }
    6.27 +    NameList *names() const {
    6.28 +        return names_;
    6.29 +    }
    6.30 +
    6.31 +    bool importAllNames() const {
    6.32 +        return names_ && names_->empty();
    6.33 +    }
    6.34  
    6.35    private:
    6.36      PathComponent *path_;
    6.37      ScopedRoot<Importable> source_;
    6.38      unsigned importIndex_;
    6.39 +    NameList *names_;
    6.40  };
    6.41  
    6.42  typedef StructureStatement::FieldList FieldList;
     7.1 --- a/src/compiler/CompileContext.cpp	Sun Jan 06 13:56:56 2013 -0800
     7.2 +++ b/src/compiler/CompileContext.cpp	Sat Jan 12 16:13:46 2013 -0800
     7.3 @@ -271,7 +271,7 @@
     7.4  CompileContext::compile()
     7.5  {
     7.6      // Phase 1. Parse all modules we're importing. This process may load new
     7.7 -    // modules off disk, and add them to the parse queue.
     7.8 +    // modules off disk and add them to the parse queue.
     7.9      while (!unparsed_.empty()) {
    7.10          TranslationUnit *unit = unparsed_.popCopy();
    7.11  
    7.12 @@ -289,6 +289,9 @@
    7.13          if (unit->failed())
    7.14              continue;
    7.15  
    7.16 +        // Mark the module as currently in translation.
    7.17 +        unit->module()->setTranslationUnit(unit);
    7.18 +
    7.19          PopulateNamesAndTypes(zone_, *this, unit);
    7.20      }
    7.21  
    7.22 @@ -298,15 +301,12 @@
    7.23          if (unit->failed())
    7.24              continue;
    7.25  
    7.26 -        BindNamesAndTypes(zone_, *this, unit);
    7.27 -    }
    7.28 +        BindGlobals(zone_, *this, unit);
    7.29  
    7.30 -    // Phase 4. Assign types to every public name in the module.
    7.31 -    for (size_t i = 0; i < units_.length(); i++) {
    7.32 -        TranslationUnit *unit = units_[i];
    7.33          if (unit->failed())
    7.34              continue;
    7.35  
    7.36 +        BindNamesAndTypes(zone_, *this, unit);
    7.37      }
    7.38  
    7.39      // Intermediate phase. Decide which modules we should not perform
    7.40 @@ -328,6 +328,10 @@
    7.41      // Phase 5. Run modules.
    7.42      for (size_t i = 0; i < units_.length(); i++) {
    7.43          TranslationUnit *unit = units_[i];
    7.44 +
    7.45 +        // Mark the unit as no longer being translated.
    7.46 +        unit->module()->setTranslationUnit(NULL);
    7.47 +
    7.48          if (unit->failed())
    7.49              break;
    7.50  
     8.1 --- a/src/compiler/NameBinding.cpp	Sun Jan 06 13:56:56 2013 -0800
     8.2 +++ b/src/compiler/NameBinding.cpp	Sat Jan 12 16:13:46 2013 -0800
     8.3 @@ -217,6 +217,11 @@
     8.4              TypeSymbol *sym = new (pool_) TypeSymbol(scope, name, type);
     8.5              if (!registerName(scope, sym))
     8.6                  return;
     8.7 +
     8.8 +            if (scope->kind() == Scope::GLOBAL) {
     8.9 +                if (!unit_->globalScope()->exported()->append(sym))
    8.10 +                    return;
    8.11 +            }
    8.12          }
    8.13  
    8.14          int value = 0;
    8.15 @@ -236,6 +241,10 @@
    8.16              ConstantSymbol *sym = new (pool_) ConstantSymbol(scope, entry.name, entry.pos, type, box);
    8.17              if (!registerName(scope, sym))
    8.18                  return;
    8.19 +            if (scope->kind() == Scope::GLOBAL) {
    8.20 +                if (!unit_->globalScope()->exported()->append(sym))
    8.21 +                    return;
    8.22 +            }
    8.23  
    8.24              value++;
    8.25          }
    8.26 @@ -262,6 +271,9 @@
    8.27          {
    8.28              // We're in the global scope, for sure.
    8.29              assert(env_->scope()->kind() == Scope::GLOBAL);
    8.30 +
    8.31 +            if (!unit_->globalScope()->exported()->append(sym))
    8.32 +                return;
    8.33          }
    8.34  
    8.35          node->setSymbol(sym);
    8.36 @@ -504,7 +516,6 @@
    8.37      {
    8.38      }
    8.39  
    8.40 -
    8.41    protected:
    8.42      Type *buildVariableType(VariableDeclaration *node) {
    8.43          Local<Type> type(zone_, bindType(node->type(), node->quals()));
    8.44 @@ -762,7 +773,8 @@
    8.45  {
    8.46    public:
    8.47      GlobalBuilder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
    8.48 -      : NameBinderBase(zone, cc, unit)
    8.49 +      : NameBinderBase(zone, cc, unit),
    8.50 +        globalScope_(unit->globalScope())
    8.51      {
    8.52      }
    8.53  
    8.54 @@ -796,9 +808,10 @@
    8.55      }
    8.56  
    8.57      void visitNameProxy(NameProxy *proxy) {
    8.58 -        // Don't report errors here, since we'll report them later.
    8.59          Scope *scope = unit_->globalScope();
    8.60          Symbol *sym = scope->lookup(proxy->name());
    8.61 +        if (!sym)
    8.62 +            cc_.reportError(proxy->pos(), Message_IdentifierNotFound, proxy->name()->chars());
    8.63          proxy->bind(sym);
    8.64      }
    8.65  
    8.66 @@ -850,8 +863,7 @@
    8.67      }
    8.68  
    8.69      void visitImportStatement(ImportStatement *node) {
    8.70 -        // Eventually we'll handle |from| style imports as well.
    8.71 -        {
    8.72 +        if (!node->names()) {
    8.73              PathComponent *path = node->path();
    8.74              while (path->next)
    8.75                  path = path->next;
    8.76 @@ -868,12 +880,48 @@
    8.77              ImportSymbol *sym = new (pool_) ImportSymbol(unit_->importScope(), path->name, node->pos(), type, node->importIndex());
    8.78              if (!unit_->importScope()->addSymbol(sym))
    8.79                  return;
    8.80 +        } else if (node->importAllNames()) {
    8.81 +            Local<Importable> importable(zone_, unit_->module()->getImportAt(node->importIndex()));
    8.82 +            if (importable->isPackage()) {
    8.83 +                assert(false);
    8.84 +            } else {
    8.85 +                Local<Module> module(zone_, Module::cast(importable));
    8.86 +                if (!module->globals())
    8.87 +                    importAllFromTranslationUnit(node, module, module->translationUnit());
    8.88 +                else
    8.89 +                    assert(false);
    8.90 +            }
    8.91 +        }
    8.92 +    }
    8.93 +
    8.94 +  private:
    8.95 +    void importAllFromTranslationUnit(ImportStatement *node, Handle<Module> module, TranslationUnit *other) {
    8.96 +        assert(!other->failed());
    8.97 +
    8.98 +        for (size_t i = 0; i < other->globalScope()->exported()->length(); i++) {
    8.99 +            Symbol *import = other->globalScope()->exported()->at(i);
   8.100 +            assert(import->type());
   8.101 +
   8.102 +            // Check for duplicate import names.
   8.103 +            if (unit_->importScope()->localLookup(import->name())) {
   8.104 +                cc_.reportError(node->pos(), Message_DuplicateImport, import->name()->chars());
   8.105 +                return;
   8.106 +            }
   8.107 +
   8.108 +            ImplicitSymbol *sym = new (pool_) ImplicitSymbol(unit_->importScope(),
   8.109 +                                                         import->name(),
   8.110 +                                                         node->pos(),
   8.111 +                                                         import->type(),
   8.112 +                                                         node->importIndex());
   8.113 +            if (!unit_->importScope()->addSymbol(sym))
   8.114 +                return;
   8.115          }
   8.116      }
   8.117  
   8.118    private:
   8.119      StructureBufferBuilder builder_;
   8.120      Vector<ScopedRoot<Descriptor> *> descriptors_;
   8.121 +    GlobalScope *globalScope_;
   8.122  };
   8.123      
   8.124  class NameBinder : public NameBinderBase
   8.125 @@ -1093,21 +1141,22 @@
   8.126  };
   8.127  
   8.128  void
   8.129 -ke::BindNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
   8.130 +ke::BindGlobals(Zone *zone, CompileContext &cc, TranslationUnit *unit)
   8.131  {
   8.132      AutoEnterCompileContext enter(cc, unit);
   8.133  
   8.134 -    // Because of the way globals work in Pawn, we need a precursor step to
   8.135 -    // actually enter global symbols into the global struct. They're already
   8.136 -    // in the global symbol table, so we know they won't clash. This process
   8.137 -    // also binds any remaining types on global variables.
   8.138      GlobalBuilder builder(zone, cc, unit);
   8.139      Local<Struct> globals(zone, builder.build());
   8.140      if (!globals || unit->failed())
   8.141          return;
   8.142  
   8.143      unit->module()->setGlobals(globals);
   8.144 +}
   8.145  
   8.146 +void
   8.147 +ke::BindNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit)
   8.148 +{
   8.149 +    AutoEnterCompileContext enter(cc, unit);
   8.150      NameBinder binder(zone, cc, unit);
   8.151      binder.bind();
   8.152  }
     9.1 --- a/src/compiler/NameBinding.h	Sun Jan 06 13:56:56 2013 -0800
     9.2 +++ b/src/compiler/NameBinding.h	Sat Jan 12 16:13:46 2013 -0800
     9.3 @@ -29,9 +29,17 @@
     9.4  class CompileContext;
     9.5  struct TranslationUnit;
     9.6  
     9.7 -// Creates symbols and types for names that are global or can be derived from a global.
     9.8 +// Creates symbols and types for names that are global or can be derived from
     9.9 +// a global. This phase also populates global scopes with lists of exported
    9.10 +// symbols.
    9.11  void PopulateNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit);
    9.12  
    9.13 +// Because of the way globals work in Pawn, we need a precursor step to
    9.14 +// actually enter global symbols into the global struct. They're already in
    9.15 +// the global symbol table, so we know they won't clash. This process also
    9.16 +// binds any remaining types on global variables.
    9.17 +void BindGlobals(Zone *zone, CompileContext &cc, TranslationUnit *unit);
    9.18 +
    9.19  // Bind all outstanding names and finalize all unfinished types.
    9.20  void BindNamesAndTypes(Zone *zone, CompileContext &cc, TranslationUnit *unit);
    9.21  
    10.1 --- a/src/compiler/Parser.cpp	Sun Jan 06 13:56:56 2013 -0800
    10.2 +++ b/src/compiler/Parser.cpp	Sat Jan 12 16:13:46 2013 -0800
    10.3 @@ -1240,13 +1240,19 @@
    10.4  }
    10.5  
    10.6  ImportStatement *
    10.7 -Parser::import()
    10.8 +Parser::import(TokenKind kind)
    10.9  {
   10.10      SourcePosition pos = scanner_.begin();
   10.11  
   10.12 -    // import       ::= import_path
   10.13 -    // import_path  ::= name |
   10.14 -    //                  name "." import_path
   10.15 +    // import       ::= "from" import_path "import" import_names
   10.16 +    //                | "import" import_path
   10.17 +    //                | "import" import_path ".*"
   10.18 +    // import_path  ::= name
   10.19 +    //                | name "." import_path
   10.20 +    // import_names ::= "*"
   10.21 +    //                | import_name_list
   10.22 +    // import_name_list ::= name
   10.23 +    //                    | name "," import_name_list
   10.24  
   10.25      Local<String> name(zone_, expectName());
   10.26      if (!name)
   10.27 @@ -1255,7 +1261,16 @@
   10.28      PathComponent *root = new (pool_) PathComponent(NewScopedRoot<String>(pool_, name), NULL);
   10.29      PathComponent *current = root;
   10.30  
   10.31 +    // NULL namelist means that we do not import any names. An empty namelist
   10.32 +    // means we import all names.
   10.33 +    NameList *names = NULL;
   10.34 +
   10.35      while (match(TOK_DOT)) {
   10.36 +        if (kind == TOK_IMPORT && match(TOK_STAR)) {
   10.37 +            names = new (pool_) NameList();
   10.38 +            break;
   10.39 +        }
   10.40 +
   10.41          if ((name = expectName()) == NULL)
   10.42              return NULL;
   10.43  
   10.44 @@ -1263,7 +1278,31 @@
   10.45          current = current->next;
   10.46      }
   10.47  
   10.48 -    return new (pool_) ImportStatement(pos, root);
   10.49 +    if (kind == TOK_FROM) {
   10.50 +        if (!expect(TOK_IMPORT))
   10.51 +            return NULL;
   10.52 +
   10.53 +        names = new (pool_) NameList();
   10.54 +
   10.55 +        if (!match(TOK_STAR)) {
   10.56 +            if (!matchName(name.address())) {
   10.57 +                cc_.reportError(scanner_.begin(), Message_BadImportFrom);
   10.58 +                return NULL;
   10.59 +            }
   10.60 +
   10.61 +            if (!name || !names->append(NewScopedRoot<String>(pool_, name)))
   10.62 +                return NULL;
   10.63 +
   10.64 +            while (match(TOK_COMMA)) {
   10.65 +                if ((name = expectName()) == NULL)
   10.66 +                    return NULL;
   10.67 +                if (!names->append(NewScopedRoot<String>(pool_, name)))
   10.68 +                    return NULL;
   10.69 +            }
   10.70 +        }
   10.71 +    }
   10.72 +
   10.73 +    return new (pool_) ImportStatement(pos, root, names);
   10.74  }
   10.75  
   10.76  Statement *
   10.77 @@ -1391,12 +1430,13 @@
   10.78                  return NULL;
   10.79              break;
   10.80  
   10.81 +          case TOK_FROM:
   10.82            case TOK_IMPORT:
   10.83            {
   10.84              scanner_.scan();
   10.85              if (statements->length())
   10.86                  cc_.reportError(scanner_.begin(), Message_ImportsMustBeFirst);
   10.87 -            ImportStatement *stmt = import();
   10.88 +            ImportStatement *stmt = import(kind);
   10.89              if (!stmt)
   10.90                  return NULL;
   10.91              if (!imports_->append(stmt))
    11.1 --- a/src/compiler/Parser.h	Sun Jan 06 13:56:56 2013 -0800
    11.2 +++ b/src/compiler/Parser.h	Sat Jan 12 16:13:46 2013 -0800
    11.3 @@ -93,7 +93,7 @@
    11.4      Statement *localStatement();
    11.5      Statement *globalStatement();
    11.6      Statement *returnStatement();
    11.7 -    ImportStatement *import();
    11.8 +    ImportStatement *import(TokenKind kind);
    11.9  
   11.10    public:
   11.11      Parser(Zone *zone, CompileContext &cc, const char *stream, size_t length);
    12.1 --- a/src/compiler/Scanner.cpp	Sun Jan 06 13:56:56 2013 -0800
    12.2 +++ b/src/compiler/Scanner.cpp	Sat Jan 12 16:13:46 2013 -0800
    12.3 @@ -438,6 +438,8 @@
    12.4          return TOK_SIZEOF;
    12.5      if (!strcmp(str,  "import"))
    12.6          return TOK_IMPORT;
    12.7 +    if (!strcmp(str,  "from"))
    12.8 +        return TOK_FROM;
    12.9      return TOK_NONE;
   12.10  }
   12.11  
    13.1 --- a/src/compiler/Scopes.h	Sun Jan 06 13:56:56 2013 -0800
    13.2 +++ b/src/compiler/Scopes.h	Sat Jan 12 16:13:46 2013 -0800
    13.3 @@ -101,8 +101,13 @@
    13.4    public:
    13.5      static GlobalScope *New(PoolAllocator &pool, ImportScope *parent);
    13.6  
    13.7 +    PoolList<Symbol *> *exported() {
    13.8 +        return &exported_;
    13.9 +    }
   13.10 +
   13.11    private:
   13.12      GlobalScope(PoolAllocator &pool, ImportScope *parent);
   13.13 +    PoolList<Symbol *> exported_;
   13.14  };
   13.15  
   13.16  class ImportScope : public Scope
    14.1 --- a/src/compiler/SemanticAnalysis.cpp	Sun Jan 06 13:56:56 2013 -0800
    14.2 +++ b/src/compiler/SemanticAnalysis.cpp	Sat Jan 12 16:13:46 2013 -0800
    14.3 @@ -559,6 +559,23 @@
    14.4      return true;
    14.5  }
    14.6  
    14.7 +static unsigned
    14.8 +BindImplicitName(Module *from, ImplicitSymbol *sym)
    14.9 +{
   14.10 +    if (sym->bound())
   14.11 +        return sym->fieldIndex();
   14.12 +
   14.13 +    Module *module = Module::cast(from->getImportAt(sym->index()));
   14.14 +    StructMap *map = module->globals()->map();
   14.15 +
   14.16 +    unsigned fieldIndex;
   14.17 +    Descriptor *desc = map->type()->lookupField(sym->name(), &fieldIndex);
   14.18 +    assert(desc && desc->type() == sym->type());
   14.19 +
   14.20 +    sym->bind(fieldIndex);
   14.21 +    return fieldIndex;
   14.22 +}
   14.23 +
   14.24  void
   14.25  SemanticAnalysis::visitNameProxy(NameProxy *proxy)
   14.26  {
   14.27 @@ -572,6 +589,16 @@
   14.28          break;
   14.29        }
   14.30  
   14.31 +      case Symbol::kImplicit:
   14.32 +      {
   14.33 +        ImplicitSymbol *import = sym->toImplicit();
   14.34 +        unsigned fieldIndex = BindImplicitName(unit_->module(), import);
   14.35 +
   14.36 +        hir_ = new (pool_) HImport(proxy, zone_->types()->getImportable(), import->index());
   14.37 +        hir_ = new (pool_) HField(proxy, hir_, sym->type(), fieldIndex);
   14.38 +        break;
   14.39 +      }
   14.40 +
   14.41        case Symbol::kConstant:
   14.42        {
   14.43          ConstantSymbol *val = sym->toConstant();
    15.1 --- a/src/compiler/Symbols.h	Sun Jan 06 13:56:56 2013 -0800
    15.2 +++ b/src/compiler/Symbols.h	Sat Jan 12 16:13:46 2013 -0800
    15.3 @@ -39,7 +39,9 @@
    15.4      /* A named type (class struct, typedef, etc) produces a TypeSymbol. */ \
    15.5      _(Type)             \
    15.6      /* An import name. */ \
    15.7 -    _(Import)
    15.8 +    _(Import)           \
    15.9 +    /* A name implicitly derived from an import. */ \
   15.10 +    _(Implicit)
   15.11  
   15.12  #define _(name)     class name##Symbol;
   15.13  SYMBOL_KINDS(_)
   15.14 @@ -230,6 +232,40 @@
   15.15        unsigned index_;
   15.16  };
   15.17  
   15.18 +class ImplicitSymbol : public Symbol
   15.19 +{
   15.20 +  public:
   15.21 +    ImplicitSymbol(Scope *scope, Handle<String> name, const SourcePosition &pos, Handle<Type> type,
   15.22 +                 unsigned index)
   15.23 +      : Symbol(scope, name, pos),
   15.24 +        index_(index),
   15.25 +        fieldIndex_(unsigned(-1))
   15.26 +    {
   15.27 +        type_ = type;
   15.28 +    }
   15.29 +
   15.30 +    bool bound() const {
   15.31 +        return fieldIndex_ != unsigned(-1);
   15.32 +    }
   15.33 +    Kind kind() const {
   15.34 +        return kImplicit;
   15.35 +    }
   15.36 +    unsigned index() const {
   15.37 +        return index_;
   15.38 +    }
   15.39 +    void bind(unsigned fieldIndex) {
   15.40 +        fieldIndex_ = fieldIndex;
   15.41 +    }
   15.42 +    unsigned fieldIndex() const {
   15.43 +        assert(bound());
   15.44 +        return fieldIndex_;
   15.45 +    }
   15.46 +
   15.47 +  private:
   15.48 +    unsigned index_;
   15.49 +    unsigned fieldIndex_;
   15.50 +};
   15.51 +
   15.52  }
   15.53  
   15.54  #endif // _include_sp2_symbol_h_
    16.1 --- a/src/compiler/Token.h	Sun Jan 06 13:56:56 2013 -0800
    16.2 +++ b/src/compiler/Token.h	Sat Jan 12 16:13:46 2013 -0800
    16.3 @@ -61,6 +61,7 @@
    16.4      _(INT,                "<int>")                      \
    16.5      _(SIZEOF,             "<sizeof>")                   \
    16.6      _(IMPORT,             "<import>")                   \
    16.7 +    _(FROM,               "<from>")                     \
    16.8      _(ELLIPSES,           "...")                        \
    16.9      _(PLUS,               "+")                          \
   16.10      _(MINUS,              "-")                          \
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/tests/basic/import-sysroot-all.out	Sat Jan 12 16:13:46 2013 -0800
    17.3 @@ -0,0 +1,1 @@
    17.4 +5 is 5.000000
    18.1 --- a/tests/basic/import-sysroot-all.sp	Sun Jan 06 13:56:56 2013 -0800
    18.2 +++ b/tests/basic/import-sysroot-all.sp	Sat Jan 12 16:13:46 2013 -0800
    18.3 @@ -1,4 +1,4 @@
    18.4 -import shell.*;
    18.5 +from shell import *;
    18.6  
    18.7  public main()
    18.8  {
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/tests/basic/import-sysroot-module.out	Sat Jan 12 16:13:46 2013 -0800
    19.3 @@ -0,0 +1,1 @@
    19.4 +5 is 5.000000
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/tests/basic/import-sysroot-module.sp	Sat Jan 12 16:13:46 2013 -0800
    20.3 @@ -0,0 +1,9 @@
    20.4 +import shell;
    20.5 +
    20.6 +public main()
    20.7 +{
    20.8 +    shell.PrintNum(5);
    20.9 +    shell.PrintString(" is ");
   20.10 +    shell.PrintFloat(5.0);
   20.11 +}
   20.12 +
    21.1 --- a/tests/basic/import-sysroot-select.out	Sun Jan 06 13:56:56 2013 -0800
    21.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.3 @@ -1,1 +0,0 @@
    21.4 -5 is 5.000000
    22.1 --- a/tests/basic/import-sysroot-select.sp	Sun Jan 06 13:56:56 2013 -0800
    22.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.3 @@ -1,9 +0,0 @@
    22.4 -import shell;
    22.5 -
    22.6 -public main()
    22.7 -{
    22.8 -    shell.PrintNum(5);
    22.9 -    shell.PrintString(" is ");
   22.10 -    shell.PrintFloat(5.0);
   22.11 -}
   22.12 -