src/compiler/CompileContext.cpp
changeset 251 ca99a81745fe
parent 250 0998a43cc155
child 252 1dee2330aa78
     1.1 --- a/src/compiler/CompileContext.cpp	Sat Dec 29 00:55:38 2012 -0800
     1.2 +++ b/src/compiler/CompileContext.cpp	Tue Jan 01 15:34:07 2013 -0800
     1.3 @@ -1,23 +1,25 @@
     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 <stdio.h>
    1.26  #include "../Zone.h"
    1.27  #include "../Interpreter.h"
    1.28 +#include "../Packages.h"
    1.29 +#include "../FileSystem.h"
    1.30  #include "Scanner.h"
    1.31  #include "CompileContext.h"
    1.32  #include "Parser.h"
    1.33 @@ -38,28 +40,57 @@
    1.34  CompileContext::~CompileContext()
    1.35  {
    1.36      for (size_t i = 0; i < units_.length(); i++)
    1.37 -        delete units_[i];
    1.38 +        units_[i]->destroy();
    1.39  }
    1.40  
    1.41  bool
    1.42 -CompileContext::addTranslationUnit(TranslationUnit *unit)
    1.43 +CompileContext::initialize(Handle<Package> package, const char *name)
    1.44  {
    1.45 -    if (!units_.append(unit))
    1.46 +    size_t len = strlen(name);
    1.47 +    AutoFree<char> path((char *)zone_->malloc(len + 1));
    1.48 +    if (!*path)
    1.49 +        return false;
    1.50 +
    1.51 +    strcpy(*path, name);
    1.52 +    if (len > 3 && strcmp(&name[len - 3], ".sp") == 0)
    1.53 +        (*path)[len - 3] = '\0';
    1.54 +
    1.55 +    Local<String> strname(zone_, zone_->makeSymbol(*path));
    1.56 +    if (!strname)
    1.57          return false;
    1.58  
    1.59 -    if (!unparsed_.append(unit))
    1.60 +    PathComponent p(new ScopedRoot<String>(strname), NULL);
    1.61 +
    1.62 +    Local<Importable> importable(zone_);
    1.63 +    if (!zone_->packages()->findOrAdd(package, &p, importable.address()))
    1.64 +        return false;
    1.65 +
    1.66 +    // If we couldn't find anything on the filesystem to match, we error out
    1.67 +    // early.
    1.68 +    if (!importable) {
    1.69 +        zone_->reportError(Message_CannotImportPath, *path);
    1.70          return false;
    1.71 +    }
    1.72 +
    1.73 +    if (importable->isModule()) {
    1.74 +        Local<Module> module(zone_, Module::cast(importable));
    1.75 +        if (!add(module))
    1.76 +            return true;
    1.77 +    } else {
    1.78 +        // nyi
    1.79 +        assert(false);
    1.80 +    }
    1.81  
    1.82      return true;
    1.83  }
    1.84  
    1.85  char *
    1.86 -CompileContext::loadSource(const char *file, size_t *lengthp)
    1.87 +CompileContext::loadSource(Handle<Module> module, size_t *lengthp)
    1.88  {
    1.89      char *bytes = NULL;
    1.90      size_t length;
    1.91  
    1.92 -    FILE *fp = fopen(file, "rb");
    1.93 +    FILE *fp = fopen(module->path()->chars(), "rb");
    1.94      if (!fp) {
    1.95          reportError(SourcePosition(), Message_CantOpenFile);
    1.96          return NULL;
    1.97 @@ -94,12 +125,10 @@
    1.98  bool
    1.99  CompileContext::parse(TranslationUnit *unit)
   1.100  {
   1.101 -    AutoEnterCompileContext enter(*this, unit);
   1.102 -
   1.103      assert(!unit->tree_);
   1.104  
   1.105      size_t length;
   1.106 -    char *source = loadSource(unit->path_, &length);
   1.107 +    char *source = loadSource(unit->module(), &length);
   1.108      if (!source)
   1.109          return false;
   1.110  
   1.111 @@ -110,26 +139,53 @@
   1.112      return true;
   1.113  }
   1.114  
   1.115 -void
   1.116 +bool
   1.117  CompileContext::evaluateImports(TranslationUnit *unit)
   1.118  {
   1.119 -    if (units_.length() > 1)
   1.120 -        return;
   1.121 +    PoolList<ImportStatement *> *imports = unit->tree()->imports();
   1.122 +
   1.123 +    for (size_t i = 0; i < imports->length(); i++) {
   1.124 +        ImportStatement *import = imports->at(i);
   1.125 +
   1.126 +        // Step 1. Crawl the path until we find a valid file to load.
   1.127 +        Local<Importable> obj(zone_);
   1.128 +        Local<Package> package(zone_, unit->module()->parent());
   1.129 +        if (!zone_->packages()->findOrAdd(package, import->path(), obj.address()))
   1.130 +            return false;
   1.131 +        if (!obj) {
   1.132 +            PathComponent *path = import->path();
   1.133 +            while (path->next)
   1.134 +                path = path->next;
   1.135 +            reportError(import->pos(), Message_CannotImportPath, path->name->chars());
   1.136 +            return false;
   1.137 +        }
   1.138  
   1.139 -#if 0
   1.140 -    // For now we hardcode this...
   1.141 -    TranslationUnit *u2 = new (ZONE()->pool()) TranslationUnit();
   1.142 -    u2->path_ = "C:\\Users\\dvander\\jitcraft\\jitcraft-2\\src\\Debug\\wizard.sp";
   1.143 +        // If the object is a package, we will attempt to execute it
   1.144 +        // immediately after resolving imports.
   1.145 +        if (obj->isPackage()) {
   1.146 +            assert(false);
   1.147 +        } else {
   1.148 +            Local<Module> module(zone_, Module::cast(obj));
   1.149 +            if (!add(module))
   1.150 +                return false;
   1.151 +        }
   1.152 +    }
   1.153  
   1.154 -    ImportStatement *stmt = unit->tree()->imports()->at(0)->toImportStatement();
   1.155 -    stmt->setImportSource(u2);
   1.156 +    return true;
   1.157 +}
   1.158  
   1.159 -    if (!u2->dependents_.append(unit))
   1.160 +bool
   1.161 +CompileContext::add(Handle<Module> module)
   1.162 +{
   1.163 +    if (module->compiled())
   1.164 +        return true;
   1.165 +
   1.166 +    TranslationUnit *tu = new (zone_->pool()) TranslationUnit(module);
   1.167 +
   1.168 +    if (!unparsed_.append(tu) || !units_.append(tu))
   1.169          return false;
   1.170  
   1.171 -    if (!addTranslationUnit(u2))
   1.172 -        return false;
   1.173 -#endif
   1.174 +    return true;
   1.175  }
   1.176  
   1.177  bool
   1.178 @@ -165,6 +221,7 @@
   1.179      while (!unparsed_.empty()) {
   1.180          TranslationUnit *unit = unparsed_.popCopy();
   1.181  
   1.182 +        AutoEnterCompileContext enter(*this, unit);
   1.183          if (!parse(unit))
   1.184              continue;
   1.185  
   1.186 @@ -238,7 +295,7 @@
   1.187              if (!unit->errors()->length())
   1.188                  continue;
   1.189  
   1.190 -            reporter->beginCompilationErrors(unit->path_);
   1.191 +            reporter->beginCompilationErrors(unit->module()->path()->chars());
   1.192              for (size_t j = 0; j < unit->errors()->length(); j++) {
   1.193                  const CompileError &error = unit->errors()->at(j);
   1.194                  reporter->reportCompilationError(error.message, error.line, error.col);
   1.195 @@ -285,7 +342,8 @@
   1.196      va_end(ap);
   1.197  }
   1.198  
   1.199 -TranslationUnit::~TranslationUnit()
   1.200 +void
   1.201 +TranslationUnit::destroy()
   1.202  {
   1.203      for (size_t i = 0; i < errors_.length(); i++)
   1.204          FreeErrorMessage(errors_[i].message);