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);