src/compiler/NameBinding.cpp
changeset 261 219b49bf4a03
parent 260 05de34f712fe
child 263 ba85a47ee414
     1.1 --- a/src/compiler/NameBinding.cpp	Sat Jan 12 16:35:26 2013 -0800
     1.2 +++ b/src/compiler/NameBinding.cpp	Sun Jan 27 17:34:30 2013 -0800
     1.3 @@ -137,12 +137,14 @@
     1.4          return;
     1.5      }
     1.6  
     1.7 -    bool declareSystemType(ImportScope *scope, const char *name, Handle<Type> type) {
     1.8 +    bool declareSystemType(ImportScope *scope, const char *name, Handle<Type> effective) {
     1.9          Local<String> tag(zone_, zone_->makeSymbol(name));
    1.10          if (!tag)
    1.11              return false;
    1.12  
    1.13 -        TypeSymbol *sym = new (pool_) TypeSymbol(scope, tag, type);
    1.14 +        Local<Type> type(zone_, zone_->types()->getType());
    1.15 +
    1.16 +        TypeSymbol *sym = new (pool_) TypeSymbol(scope, tag, type, effective);
    1.17          return scope->addSymbol(sym);
    1.18      }
    1.19  
    1.20 @@ -214,7 +216,8 @@
    1.21              return;
    1.22  
    1.23          if (name) {
    1.24 -            TypeSymbol *sym = new (pool_) TypeSymbol(scope, name, type);
    1.25 +            Local<Type> symType(zone_, zone_->types()->getType());
    1.26 +            TypeSymbol *sym = new (pool_) TypeSymbol(scope, name, symType, type);
    1.27              if (!registerName(scope, sym))
    1.28                  return;
    1.29  
    1.30 @@ -224,6 +227,10 @@
    1.31              }
    1.32          }
    1.33  
    1.34 +        // We want each field of the expression to qualify as a constant expression.
    1.35 +        if ((type = zone_->types()->qualify(type, TypeQual_ConstExpr)) == NULL)
    1.36 +            return;
    1.37 +        
    1.38          int value = 0;
    1.39          for (size_t i = 0; i < node->entries()->length(); i++) {
    1.40              EnumStatement::Entry &entry = node->entries()->at(i);
    1.41 @@ -237,7 +244,7 @@
    1.42                  assert(box.type() == PrimitiveType_Int32);
    1.43                  value = box.toInt();
    1.44              }
    1.45 -            
    1.46 +         
    1.47              ConstantSymbol *sym = new (pool_) ConstantSymbol(scope, entry.name, entry.pos, type, box);
    1.48              if (!registerName(scope, sym))
    1.49                  return;
    1.50 @@ -246,6 +253,7 @@
    1.51                      return;
    1.52              }
    1.53  
    1.54 +            entry.sym = sym;
    1.55              value++;
    1.56          }
    1.57      }
    1.58 @@ -756,7 +764,7 @@
    1.59                  return NULL;
    1.60              }
    1.61  
    1.62 -            type = sym->type();
    1.63 +            type = sym->toType()->effective();
    1.64          }
    1.65  
    1.66          return zone_->types()->qualify(type, quals);
    1.67 @@ -771,6 +779,18 @@
    1.68  
    1.69  class GlobalBuilder : public NameBinderBase
    1.70  {
    1.71 +    typedef ScopedRoot<Descriptor> ScopedDescriptor;
    1.72 +    struct PrimitiveFill {
    1.73 +        ScopedDescriptor *desc;
    1.74 +        BoxedPrimitive prim;
    1.75 +
    1.76 +        PrimitiveFill(ScopedDescriptor *desc, BoxedPrimitive prim)
    1.77 +          : desc(desc),
    1.78 +            prim(prim)
    1.79 +        {
    1.80 +        }
    1.81 +    };
    1.82 +
    1.83    public:
    1.84      GlobalBuilder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
    1.85        : NameBinderBase(zone, cc, unit),
    1.86 @@ -788,6 +808,17 @@
    1.87              stmt->accept(this);
    1.88          }
    1.89  
    1.90 +        Local<Struct> globals(zone_, createGlobals());
    1.91 +        if (!globals)
    1.92 +            return NULL;
    1.93 +
    1.94 +        populate(globals);
    1.95 +
    1.96 +        return globals;
    1.97 +    }
    1.98 +
    1.99 +  private:
   1.100 +    Struct *createGlobals() {
   1.101          Local<FixedArray> descs(zone_, FixedArray::New(zone_, descriptors_.length(), Heap::Tenure_Old));
   1.102          if (!descs)
   1.103              return NULL;
   1.104 @@ -804,7 +835,47 @@
   1.105          return Struct::New(zone_, map, Heap::Tenure_Old);
   1.106      }
   1.107  
   1.108 +    void populate(Handle<Struct> globals) {
   1.109 +        // This is a huge hack, but it's probably better than a full extra
   1.110 +        // pass. The problem is that until we have all the descriptors, we
   1.111 +        // can't start setting constexprs in the struct, and we need to set
   1.112 +        // them now so they're available during full semantic analysis. To
   1.113 +        // work around this, we build up the list of values we need to set
   1.114 +        // as we build up descriptors, and then populate the global struct
   1.115 +        // with this set.
   1.116 +        //
   1.117 +        // Note, this code is also kind of dead until we support linking. We
   1.118 +        // handle constexprs explicitly in importFrom(), by sniffing out the
   1.119 +        // symbol type. That code will go away later.
   1.120 +        for (size_t i = 0; i < primitiveFills_.length(); i++) {
   1.121 +            const PrimitiveFill &fill = primitiveFills_[i];
   1.122 +            assert(fill.prim.type() == PrimitiveType_Int32);
   1.123 +            globals->set(*fill.desc, fill.prim.toInt());
   1.124 +        }
   1.125 +    }
   1.126 +
   1.127 +  public:
   1.128      void visitEnumStatement(EnumStatement *stmt) {
   1.129 +        if (stmt->visibility() != TOK_PUBLIC || !stmt->name())
   1.130 +            return;
   1.131 +
   1.132 +        Local<Type> type(zone_, zone_->types()->getType());
   1.133 +        Descriptor *desc = Descriptor::New(zone_, stmt->name(), type, Descriptor::Public);
   1.134 +        if (!desc)
   1.135 +            return;
   1.136 +        if (!descriptors_.append(new (pool_) ScopedRoot<Descriptor>(desc)))
   1.137 +            return;
   1.138 +
   1.139 +        for (size_t i = 0; i < stmt->entries()->length(); i++) {
   1.140 +            EnumStatement::Entry &e = stmt->entries()->at(i);
   1.141 +            ScopedDescriptor *desc = new (pool_) ScopedDescriptor(Descriptor::New(zone_, e.name, e.sym->type(), Descriptor::Public));
   1.142 +            if (!desc || !descriptors_.append(desc))
   1.143 +                return;
   1.144 +
   1.145 +            // Save the value so we can export it immediately.
   1.146 +            if (!primitiveFills_.append(PrimitiveFill(desc, e.sym->value())))
   1.147 +                return;
   1.148 +        }
   1.149      }
   1.150  
   1.151      void visitNameProxy(NameProxy *proxy) {
   1.152 @@ -917,11 +988,33 @@
   1.153              return false;
   1.154          }
   1.155  
   1.156 -        ImplicitSymbol *sym = new (pool_) ImplicitSymbol(unit_->importScope(),
   1.157 -                                                        import->name(),
   1.158 -                                                        node->pos(),
   1.159 -                                                        import->type(),
   1.160 -                                                        node->importIndex());
   1.161 +        Symbol *sym;
   1.162 +        if (import->isType()) {
   1.163 +            // Fuck it, make a TypeSymbol instead of an ImplicitSymbol. This
   1.164 +            // makes bindType() much simpler. We may run into problems
   1.165 +            // implementing linking, but it seems unlikely, as long as we are
   1.166 +            // exporting Types in module structs.
   1.167 +            Local<Type> type(zone_, zone_->types()->getType());
   1.168 +            sym = new (pool_) TypeSymbol(unit_->importScope(),
   1.169 +                                         import->name(),
   1.170 +                                         type,
   1.171 +                                         import->toType()->effective());
   1.172 +        } else if (import->isConstant()) {
   1.173 +            // Same deal. No reason to lookup in the module globals if we
   1.174 +            // already have a symbol.
   1.175 +            sym = new (pool_) ConstantSymbol(unit_->importScope(),
   1.176 +                                             import->name(),
   1.177 +                                             node->pos(),
   1.178 +                                             import->type(),
   1.179 +                                             import->toConstant()->value());
   1.180 +        } else {
   1.181 +            sym = new (pool_) ImplicitSymbol(unit_->importScope(),
   1.182 +                                             import->name(),
   1.183 +                                             node->pos(),
   1.184 +                                             import->type(),
   1.185 +                                             node->importIndex());
   1.186 +        }
   1.187 +
   1.188          if (!unit_->importScope()->addSymbol(sym))
   1.189              return false;
   1.190  
   1.191 @@ -963,6 +1056,7 @@
   1.192      StructureBufferBuilder builder_;
   1.193      Vector<ScopedRoot<Descriptor> *> descriptors_;
   1.194      GlobalScope *globalScope_;
   1.195 +    Vector<PrimitiveFill> primitiveFills_;
   1.196  };
   1.197      
   1.198  class NameBinder : public NameBinderBase