Refactor compilation process around the new concept of packages.
Refactor compilation process around the new concept of packages.
1.1 --- a/AMBuildScript Sat Dec 29 00:55:38 2012 -0800
1.2 +++ b/AMBuildScript Tue Jan 01 15:34:07 2013 -0800
1.3 @@ -68,8 +68,12 @@
1.4 self.compiler.AddToListVar('CXXFLAGS', '-Wno-invalid-offsetof')
1.5
1.6 # This would otherwise forbid ((x = y) == NULL) in clang apparently.
1.7 - if self.vendor == 'clang':
1.8 + if self.vendor == 'clang' and cxx.majorVersion > 1:
1.9 self.compiler.AddToListVar('CXXFLAGS', '-Wno-null-arithmetic')
1.10 + if self.vendor == 'clang' and \
1.11 + cxx.majorVersion >= 3 and \
1.12 + cxx.minorVersion >= 3:
1.13 + self.compiler.AddToListVar('CXXFLAGS', '-Wno-unused-private-field')
1.14
1.15 if (self.vendor == 'gcc' and cxx.majorVersion >= 4 and cxx.minorVersion >= 7) or \
1.16 (self.vendor == 'clang' and cxx.majorVersion >= 3):
2.1 --- a/include/keima.h Sat Dec 29 00:55:38 2012 -0800
2.2 +++ b/include/keima.h Tue Jan 01 15:34:07 2013 -0800
2.3 @@ -35,6 +35,7 @@
2.4 namespace Ke {
2.5
2.6 class Function;
2.7 +class Package;
2.8
2.9 /*
2.10 * A Handle is a safe pointer that holds an object reference, such that it
2.11 @@ -251,6 +252,8 @@
2.12 class KE_EXPORT String
2.13 {
2.14 public:
2.15 + static Local<String> NewAscii(const char *str);
2.16 +
2.17 // Returns the length of the string, in bytes.
2.18 unsigned length();
2.19
2.20 @@ -266,6 +269,9 @@
2.21 // Returns the name of a function, which may be NULL. If not NULL, the
2.22 // string is guaranteed to be interned.
2.23 Local<String> name();
2.24 +
2.25 + // Returns the package the function was created in.
2.26 + Local<Package> package();
2.27 };
2.28
2.29 // A pubvar is an ISourcePawnEngine-compatible structure that holds information
2.30 @@ -278,14 +284,47 @@
2.31 Local<String> name();
2.32 };
2.33
2.34 -// A module represents a single compiled file, and contains functions and
2.35 -// global variables for that file (as well as exported types).
2.36 -class KE_EXPORT Module
2.37 +// A package is a collection of compiled files and possibly sub-packages.
2.38 +// Internally, packages are used to implement the "import" statement. However,
2.39 +// the host application can also create packages to organize related files,
2.40 +// restrict import visibility, or implement hot swapping of loaded modules.
2.41 +class KE_EXPORT Package
2.42 {
2.43 public:
2.44 - // Sets the native identity pointer, which is passed as the first argument
2.45 - // to natives.
2.46 - void setNativeIdentity(void *ptr);
2.47 + enum {
2.48 + Normal = 0,
2.49 +
2.50 + // The package cannot be accessed from any import statement.
2.51 + Hidden = (1 << 0),
2.52 +
2.53 + // Source files compiled in this package cannot import names in the
2.54 + // package.
2.55 + Jailed = (1 << 1)
2.56 + };
2.57 +
2.58 + // Creates a package. The parent package may be NULL. The name can be NULL
2.59 + // as well. |path| must be a filesystem path, which will be normalized
2.60 + // according to OS-specific rules.
2.61 + static Local<Package> New(Handle<Package> parent,
2.62 + Handle<String> name,
2.63 + const char *path,
2.64 + unsigned flags);
2.65 +
2.66 + // Returns the name of the package, which may be NULL. The string is
2.67 + // guaranteed to be interned.
2.68 + Local<String> name();
2.69 +
2.70 + // Returns the full path of the package. The string is guaranteed to be
2.71 + // interned.
2.72 + Local<String> path();
2.73 +
2.74 + // Sets the package's native identity. This is a host-application defined
2.75 + // value that is passed to native callbacks. Packages created under this
2.76 + // one will automatically inherit this native identity.
2.77 + void setNativeIdentity(void *identity);
2.78 +
2.79 + // Returns the package's native identity, or NULL if none was set.
2.80 + void *getNativeIdentity();
2.81 };
2.82
2.83 class Keima
2.84 @@ -294,7 +333,7 @@
2.85 /*
2.86 * Initializes the Keima engine. This must be called exactly once before any
2.87 * other Keima functions are called. After this, it is safe to use Keima
2.88 - * on the calling thread.
2.89 + * on the calling thread only. It is not safe to race on calling this.
2.90 */
2.91 static bool Initialize();
2.92
2.93 @@ -304,10 +343,10 @@
2.94 static void Shutdown();
2.95
2.96 /*
2.97 - * Searches the call stack and returns true if the given module has any
2.98 + * Searches the call stack and returns true if the given package has any
2.99 * active code running. This is an O(n) algorithm.
2.100 */
2.101 - static bool IsInCallStack(Handle<Module> module);
2.102 + static bool IsInCallStack(Handle<Package> package);
2.103
2.104 /*
2.105 * Reclaim as much memory as possible. This pauses the calling thread
2.106 @@ -351,6 +390,29 @@
2.107
2.108 /* Sets the object that will listen for public functions. */
2.109 static void SetPublicFunctionListener(IPublicFunctionListener *listener);
2.110 +
2.111 + /*
2.112 + * Installs a system root folder. When an attempt to import locally fails,
2.113 + * the list of system roots are searched in the order they were installed.
2.114 + *
2.115 + * The given path must be absolute. It may contain a trailing slash.
2.116 + *
2.117 + * The name is an arbitrary, optional identifier that can be used to
2.118 + * build fully-qualified package identifiers.
2.119 + */
2.120 + static bool InstallSystemRoot(const char *path, const char *name);
2.121 +
2.122 + /*
2.123 + * Compiles a source file into a package and runs any initializers it has.
2.124 + * The file name must be a file name only, rather than a path. It may
2.125 + * optionally end in ".sp". If no ".sp" is provided, it is added
2.126 + * automatically.
2.127 + *
2.128 + * Note that if the file name (sans ".sp" extension) does not match the
2.129 + * regular expression /^[A-Za-z_][A-Za-z0-9_]+$/ then it will not be
2.130 + * importable from other files.
2.131 + */
2.132 + static bool Compile(Handle<Package> package, const char *name);
2.133 };
2.134
2.135 /*
2.136 @@ -464,11 +526,6 @@
2.137 } u;
2.138 };
2.139
2.140 -/*
2.141 - * Compiles a file and returns a Module.
2.142 - */
2.143 -extern bool Compile(const char *path);
2.144 -
2.145 class Internals
2.146 {
2.147 template <typename T> friend class Root;
3.1 --- a/src/AMBuild.library Sat Dec 29 00:55:38 2012 -0800
3.2 +++ b/src/AMBuild.library Tue Jan 01 15:34:07 2013 -0800
3.3 @@ -41,6 +41,7 @@
3.4 'compiler/Symbols.cpp',
3.5 'Environments.cpp',
3.6 'Exception.cpp',
3.7 + 'FileSystem.cpp',
3.8 'FixedArray.cpp',
3.9 'Functions.cpp',
3.10 'GlobalRoots.cpp',
3.11 @@ -49,6 +50,7 @@
3.12 'Modules.cpp',
3.13 'NativeTable.cpp',
3.14 'Opcodes.cpp',
3.15 + 'Packages.cpp',
3.16 'PoolAllocator.cpp',
3.17 'Reference.cpp',
3.18 'RootScopes.cpp',
4.1 --- a/src/API.cpp Sat Dec 29 00:55:38 2012 -0800
4.2 +++ b/src/API.cpp Tue Jan 01 15:34:07 2013 -0800
4.3 @@ -28,6 +28,7 @@
4.4 #include "Interpreter.h"
4.5 #include "Stack.h"
4.6 #include "Strings.h"
4.7 +#include "Packages.h"
4.8 #include "NativeTable.h"
4.9 #include "Spaces-inl.h"
4.10 #include "Heap-inl.h"
4.11 @@ -76,32 +77,35 @@
4.12 template <typename From, typename To> static inline To *
4.13 Open(Ke::Handle<From> from)
4.14 {
4.15 + if (!from)
4.16 + return NULL;
4.17 return *reinterpret_cast<To **>(*from);
4.18 }
4.19
4.20 template <typename From, typename To> static inline To *
4.21 Open(From *from)
4.22 {
4.23 + if (!from)
4.24 + return NULL;
4.25 return *reinterpret_cast<To **>(from);
4.26 }
4.27
4.28 template <typename From, typename To> static inline Ke::Local<To>
4.29 ToLocal(From *from)
4.30 {
4.31 + if (!from)
4.32 + return Ke::Local<To>();
4.33 return Ke::Local<To>(reinterpret_cast<To *>(Ke::HandleScope::CreateHandle(from)));
4.34 }
4.35
4.36 bool
4.37 -InternalCompile(const char *path)
4.38 +InternalCompile(ke::Handle<ke::Package> package, const char *name)
4.39 {
4.40 PoolScope poolScope(ZONE()->pool());
4.41 RootScope roots(ZONE());
4.42 - CompileContext cc(ZONE(), path);
4.43 + CompileContext cc(ZONE(), name);
4.44
4.45 - TranslationUnit *unit = new TranslationUnit();
4.46 - unit->path_ = path;
4.47 -
4.48 - if (!cc.addTranslationUnit(unit))
4.49 + if (!cc.initialize(package, name))
4.50 return false;
4.51
4.52 if (!cc.compile())
4.53 @@ -113,9 +117,10 @@
4.54 // This is split out from InternalCompile so the RootScope doesn't conflict
4.55 // with making a return handle.
4.56 bool
4.57 -Ke::Compile(const char *path)
4.58 +Ke::Keima::Compile(Handle<Package> argPackage, const char *name)
4.59 {
4.60 - return InternalCompile(path);
4.61 + ke::Local<ke::Package> package(ke::ZONE(), Open<Ke::Package, ke::Package>(argPackage));
4.62 + return InternalCompile(package, name);
4.63 }
4.64
4.65 void
4.66 @@ -186,12 +191,14 @@
4.67 ZONE()->globalRoots()->destroy(FromAPI(root));
4.68 }
4.69
4.70 +#if 0
4.71 bool
4.72 -Ke::Keima::IsInCallStack(Handle<Module> argModule)
4.73 +Ke::Keima::IsInCallStack(Handle<Package> package)
4.74 {
4.75 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(argModule));
4.76 return ZONE()->stack().isInCallStack(module);
4.77 }
4.78 +#endif
4.79
4.80 void
4.81 Ke::Keima::CollectGarbage()
4.82 @@ -206,10 +213,10 @@
4.83 }
4.84
4.85 void
4.86 -Ke::Module::setNativeIdentity(void *identity)
4.87 +Ke::Package::setNativeIdentity(void *identity)
4.88 {
4.89 - ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
4.90 - module->setNativeIdentity(identity);
4.91 + ke::Local<ke::Package> package(ke::ZONE(), Open<Ke::Package, ke::Package>(this));
4.92 + package->setNativeIdentity(identity);
4.93 }
4.94
4.95 unsigned
4.96 @@ -233,6 +240,18 @@
4.97 return ToLocal<ke::String, Ke::String>(fun->name());
4.98 }
4.99
4.100 +Ke::Local<Ke::Package>
4.101 +Ke::Package::New(Handle<Package> argParent,
4.102 + Handle<String> argName,
4.103 + const char *path,
4.104 + unsigned flags)
4.105 +{
4.106 + ke::Local<ke::Package> parent(ke::ZONE(), Open<Ke::Package, ke::Package>(argParent));
4.107 + ke::Local<ke::String> name(ke::ZONE(), Open<Ke::String, ke::String>(argName));
4.108 + ke::Local<ke::Package> package(ke::ZONE(), ke::Package::New(ke::ZONE(), parent, path, name, flags));
4.109 + return ToLocal<ke::Package, Ke::Package>(package);
4.110 +}
4.111 +
4.112 static inline const char *
4.113 GetInvokeTypeName(Ke::Parameter::Type type)
4.114 {
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/src/FileSystem.cpp Tue Jan 01 15:34:07 2013 -0800
5.3 @@ -0,0 +1,41 @@
5.4 +/*
5.5 + * Copyright (C) 2012 David Anderson
5.6 + *
5.7 + * This file is part of SourcePawn.
5.8 + *
5.9 + * SourcePawn is free software: you can redistribute it and/or modify it under
5.10 + * the terms of the GNU General Public License as published by the Free
5.11 + * Software Foundation, either version 3 of the License, or (at your option)
5.12 + * any later version.
5.13 + *
5.14 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
5.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
5.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
5.17 + *
5.18 + * You should have received a copy of the GNU General Public License along with
5.19 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
5.20 + */
5.21 +#include <string.h>
5.22 +#include "Zone.h"
5.23 +#include "FileSystem.h"
5.24 +
5.25 +bool
5.26 +ke::JoinPaths(Zone *zone, AutoFree<char> &result, const char *base, const char *name)
5.27 +{
5.28 + const char *sep = OS::PathSeparator();
5.29 +
5.30 + size_t baselen = strlen(base);
5.31 + size_t namelen = strlen(name);
5.32 + size_t seplen = strlen(sep);
5.33 +
5.34 + char *ptr = (char *)zone->malloc(baselen + seplen + namelen + 1);
5.35 + if (!ptr)
5.36 + return false;
5.37 +
5.38 + strcpy(ptr, base);
5.39 + strcpy(ptr + baselen, sep);
5.40 + strcpy(ptr + baselen + seplen, name);
5.41 +
5.42 + result = ptr;
5.43 + return true;
5.44 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/src/FileSystem.h Tue Jan 01 15:34:07 2013 -0800
6.3 @@ -0,0 +1,32 @@
6.4 +/*
6.5 + * Copyright (C) 2012 David Anderson
6.6 + *
6.7 + * This file is part of SourcePawn.
6.8 + *
6.9 + * SourcePawn is free software: you can redistribute it and/or modify it under
6.10 + * the terms of the GNU General Public License as published by the Free
6.11 + * Software Foundation, either version 3 of the License, or (at your option)
6.12 + * any later version.
6.13 + *
6.14 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
6.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
6.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
6.17 + *
6.18 + * You should have received a copy of the GNU General Public License along with
6.19 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
6.20 + */
6.21 +#ifndef _include_sp2_filesystem_h_
6.22 +#define _include_sp2_filesystem_h_
6.23 +
6.24 +#include "Utility.h"
6.25 +
6.26 +namespace ke {
6.27 +
6.28 +class Zone;
6.29 +
6.30 +// Joins a NULL terminated list of char pointers into a path.
6.31 +bool JoinPaths(Zone *zone, AutoFree<char> &result, const char *base, const char *name);
6.32 +
6.33 +} // namespace ke
6.34 +
6.35 +#endif // _include_sp2_filesystem_h_
7.1 --- a/src/GlobalRoots.cpp Sat Dec 29 00:55:38 2012 -0800
7.2 +++ b/src/GlobalRoots.cpp Tue Jan 01 15:34:07 2013 -0800
7.3 @@ -32,9 +32,9 @@
7.4 {
7.5 InlineList<HeapRoot>::iterator iter = roots_.begin();
7.6 while (iter != roots_.end()) {
7.7 - HeapRoot *root = *iter;
7.8 + HeapRoot *root = *iter;
7.9 iter = roots_.erase(iter);
7.10 - delete root;
7.11 + delete root;
7.12 }
7.13 }
7.14
8.1 --- a/src/Interpreter.cpp Sat Dec 29 00:55:38 2012 -0800
8.2 +++ b/src/Interpreter.cpp Tue Jan 01 15:34:07 2013 -0800
8.3 @@ -27,6 +27,7 @@
8.4 #include "Environments.h"
8.5 #include "Structures.h"
8.6 #include "NativeTable.h"
8.7 +#include "Packages.h"
8.8 #include "Heap-inl.h"
8.9
8.10 using namespace ke;
8.11 @@ -866,7 +867,7 @@
8.12 top.sp--;
8.13
8.14 int result;
8.15 - void *nativeIdentity = top.fp->code()->module()->nativeIdentity();
8.16 + void *nativeIdentity = top.fp->code()->module()->parent()->getNativeIdentity();
8.17 if (!InvokeNative(zone, native, nativeIdentity, top.sp, argc, &result))
8.18 goto error;
8.19
8.20 @@ -877,7 +878,7 @@
8.21
8.22 case OP_BITCAST:
8.23 {
8.24 - // Because the stack is a union, this is a no-ops.
8.25 + // Because the stack is a union, this is a no-op.
8.26 break;
8.27 }
8.28
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/src/List.h Tue Jan 01 15:34:07 2013 -0800
9.3 @@ -0,0 +1,119 @@
9.4 +/* vim: set ts=4 sw=4 tw=99 et:
9.5 + *
9.6 + * Copyright (C) 2012 David Anderson
9.7 + *
9.8 + * This file is part of SourcePawn.
9.9 + *
9.10 + * SourcePawn is free software: you can redistribute it and/or modify it under
9.11 + * the terms of the GNU General Public License as published by the Free
9.12 + * Software Foundation, either version 3 of the License, or (at your option)
9.13 + * any later version.
9.14 + *
9.15 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
9.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
9.18 + *
9.19 + * You should have received a copy of the GNU General Public License along with
9.20 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
9.21 + */
9.22 +#ifndef _include_sp2_list_h_
9.23 +#define _include_sp2_list_h_
9.24 +
9.25 +#include "Objects.h"
9.26 +#include "FixedArray.h"
9.27 +#include "Zone.h"
9.28 +#include "Heap-inl.h"
9.29 +#include "Handles-inl.h"
9.30 +
9.31 +namespace ke {
9.32 +
9.33 +template <typename T>
9.34 +class List : public Object
9.35 +{
9.36 + public:
9.37 + static List *New(Zone *zone, Heap::Tenure tenure = Heap::Tenure_Default) {
9.38 + Local<List> list(zone, List::cast(zone->allocate(MapKind_List, sizeof(List), tenure)));
9.39 + if (!list)
9.40 + return NULL;
9.41 +
9.42 + list->length_ = 0;
9.43 + list->array_ = NULL;
9.44 +
9.45 + return list;
9.46 + }
9.47 +
9.48 + bool append(Zone *zone, Handle<T> obj) {
9.49 + Local<List> list(zone, this);
9.50 + if (!Grow(zone, list, 1))
9.51 + return false;
9.52 +
9.53 + list->array_->set(zone, list->length_, obj);
9.54 + list->length_++;
9.55 + return true;
9.56 + }
9.57 +
9.58 + T *at(unsigned i) {
9.59 + return T::cast(array_->at(i));
9.60 + }
9.61 +
9.62 + unsigned length() {
9.63 + return length_;
9.64 + }
9.65 +
9.66 + private:
9.67 + static bool Grow(Zone *zone, Handle<List> list, unsigned amount) {
9.68 + if (!IsUint32AddSafe(list->length(), amount)) {
9.69 + zone->reportAllocationOverflow();
9.70 + return false;
9.71 + }
9.72 +
9.73 + unsigned newlen = list->length() + amount;
9.74 + if (list->array_ && newlen < list->array_->length())
9.75 + return true;
9.76 +
9.77 + unsigned maxsize = list->array_ ? list->array_->length() : 8;
9.78 + if (!IsUint32AddSafe(maxsize, amount)) {
9.79 + zone->reportAllocationOverflow();
9.80 + return false;
9.81 + }
9.82 +
9.83 + while (newlen > maxsize) {
9.84 + if (!IsUint32MultiplySafe(maxsize, 2)) {
9.85 + zone->reportAllocationOverflow();
9.86 + return false;
9.87 + }
9.88 + maxsize *= 2;
9.89 + }
9.90 +
9.91 + Local<FixedArray> array(zone, FixedArray::New(zone, maxsize, Heap::Tenure_Default));
9.92 + if (!array)
9.93 + return false;
9.94 +
9.95 + for (unsigned i = 0; i < list->length_; i++)
9.96 + array->set(zone, i, list->array_->at(i));
9.97 +
9.98 + list->array_ = array;
9.99 + return true;
9.100 + }
9.101 +
9.102 + public:
9.103 +
9.104 + // Begin GC descriptor.
9.105 + static inline size_t offsetOfArray() {
9.106 + return OFFSETOF(List, array_);
9.107 + }
9.108 + // End GC descriptor.
9.109 +
9.110 + static inline List *cast(Object *obj) {
9.111 + assert(!obj || obj->is(MapKind_List));
9.112 + return reinterpret_cast<List *>(obj);
9.113 + }
9.114 +
9.115 + private:
9.116 + unsigned length_;
9.117 + FixedArray *array_;
9.118 +};
9.119 +
9.120 +} // namespace ke
9.121 +
9.122 +#endif // _include_sp2_list_h_
10.1 --- a/src/Messages.tbl Sat Dec 29 00:55:38 2012 -0800
10.2 +++ b/src/Messages.tbl Tue Jan 01 15:34:07 2013 -0800
10.3 @@ -84,4 +84,5 @@
10.4 MSG(InvalidConstOnFormal, TypeError, "const parameters must be arrays or structs")
10.5 MSG(InvalidUncheckedCastFrom, TypeError, "cannot perform an unchecked cast on type '%s'")
10.6 MSG(InvalidUncheckedCastTo, TypeError, "cannot perform an unchecked cast to type '%s'")
10.7 -MSG(InvalidUnaryType, TypeError, "operator %s not defined for type '%s'")
10.8 \ No newline at end of file
10.9 +MSG(InvalidUnaryType, TypeError, "operator %s not defined for type '%s'")
10.10 +MSG(CannotImportPath, SyntaxError, "could not find module or import '%s'")
10.11 \ No newline at end of file
11.1 --- a/src/Modules.cpp Sat Dec 29 00:55:38 2012 -0800
11.2 +++ b/src/Modules.cpp Tue Jan 01 15:34:07 2013 -0800
11.3 @@ -23,15 +23,18 @@
11.4 using namespace ke;
11.5
11.6 Module *
11.7 -Module::New(Zone *zone)
11.8 +Module::New(Zone *zone, Handle<Package> package, Handle<String> path, Handle<String> name)
11.9 {
11.10 Local<Module> module(zone, Module::cast(zone->allocate(MapKind_Module, sizeof(Module), Heap::Tenure_Old)));
11.11 if (!module)
11.12 return NULL;
11.13
11.14 - module->file_ = NULL;
11.15 + module->parent_ = package;
11.16 + module->path_ = path;
11.17 + module->name_ = name;
11.18 module->globals_ = NULL;
11.19 module->nativeIdentity_ = NULL;
11.20 module->globals_ = NULL;
11.21 + module->unit_ = NULL;
11.22 return module;
11.23 }
12.1 --- a/src/Modules.h Sat Dec 29 00:55:38 2012 -0800
12.2 +++ b/src/Modules.h Tue Jan 01 15:34:07 2013 -0800
12.3 @@ -1,19 +1,19 @@
12.4 /*
12.5 * Copyright (C) 2012 David Anderson
12.6 *
12.7 - * This file is part of JITCraft.
12.8 + * This file is part of SourcePawn.
12.9 *
12.10 - * JITCraft is free software: you can redistribute it and/or modify it under
12.11 + * SourcePawn is free software: you can redistribute it and/or modify it under
12.12 * the terms of the GNU General Public License as published by the Free
12.13 * Software Foundation, either version 3 of the License, or (at your option)
12.14 * any later version.
12.15 *
12.16 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
12.17 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
12.18 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12.19 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12.20 *
12.21 * You should have received a copy of the GNU General Public License along with
12.22 - * JITCraft. If not, see http://www.gnu.org/licenses/.
12.23 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
12.24 */
12.25 #ifndef _include_jc_module_h_
12.26 #define _include_jc_module_h_
12.27 @@ -21,25 +21,25 @@
12.28 #include "Heap.h"
12.29 #include "Code.h"
12.30 #include "Functions.h"
12.31 +#include "Packages.h"
12.32
12.33 namespace ke {
12.34
12.35 class Environment;
12.36 class Struct;
12.37 +class Package;
12.38 +struct TranslationUnit;
12.39
12.40 -class Module : public Object
12.41 +class Module : public Importable
12.42 {
12.43 - Barriered<String> file_;
12.44 Barriered<Code> code_;
12.45 Barriered<Struct> globals_;
12.46 void *nativeIdentity_;
12.47 + TranslationUnit *unit_;
12.48
12.49 public:
12.50 - static Module *New(Zone *zone);
12.51 + static Module *New(Zone *zone, Handle<Package> package, Handle<String> path, Handle<String> name);
12.52
12.53 - String *file() {
12.54 - return file_;
12.55 - }
12.56 Code *code() {
12.57 return code_;
12.58 }
12.59 @@ -47,9 +47,22 @@
12.60 return globals_;
12.61 }
12.62
12.63 - void setPath(Handle<String> path) {
12.64 - file_ = path;
12.65 + bool compiled() {
12.66 + return !!code_;
12.67 }
12.68 +
12.69 + // Modules are pre-created, and may have their intermediate compilation
12.70 + // data attached while they are being compiled.
12.71 + bool compiling() {
12.72 + return !!unit_;
12.73 + }
12.74 + TranslationUnit *translationUnit() {
12.75 + return unit_;
12.76 + }
12.77 + void setTranslationUnit(TranslationUnit *unit) {
12.78 + unit_ = unit;
12.79 + }
12.80 +
12.81 void setCode(Handle<Code> code) {
12.82 code_ = code;
12.83 }
12.84 @@ -57,17 +70,7 @@
12.85 globals_ = globals;
12.86 }
12.87
12.88 - void *nativeIdentity() {
12.89 - return nativeIdentity_;
12.90 - }
12.91 - void setNativeIdentity(void *identity) {
12.92 - nativeIdentity_ = identity;
12.93 - }
12.94 -
12.95 // Begin GC Descriptor.
12.96 - static inline size_t offsetOfFile() {
12.97 - return OFFSETOF(Module, file_);
12.98 - }
12.99 static inline size_t offsetOfCode() {
12.100 return OFFSETOF(Module, code_);
12.101 }
13.1 --- a/src/ObjectVisitor.h Sat Dec 29 00:55:38 2012 -0800
13.2 +++ b/src/ObjectVisitor.h Tue Jan 01 15:34:07 2013 -0800
13.3 @@ -2,19 +2,19 @@
13.4 *
13.5 * Copyright (C) 2012 David Anderson
13.6 *
13.7 - * This file is part of JITCraft.
13.8 + * This file is part of SourcePawn.
13.9 *
13.10 - * JITCraft is free software: you can redistribute it and/or modify it under
13.11 + * SourcePawn is free software: you can redistribute it and/or modify it under
13.12 * the terms of the GNU General Public License as published by the Free
13.13 * Software Foundation, either version 3 of the License, or (at your option)
13.14 * any later version.
13.15 *
13.16 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
13.17 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
13.18 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13.19 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13.20 *
13.21 * You should have received a copy of the GNU General Public License along with
13.22 - * JITCraft. If not, see http://www.gnu.org/licenses/.
13.23 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
13.24 */
13.25 #ifndef _include_jc_object_visitor_h_
13.26 #define _include_jc_object_visitor_h_
13.27 @@ -31,6 +31,8 @@
13.28 #include "Environments.h"
13.29 #include "Structures.h"
13.30 #include "Box.h"
13.31 +#include "Packages.h"
13.32 +#include "List.h"
13.33
13.34 namespace ke {
13.35
13.36 @@ -113,13 +115,25 @@
13.37 return sizeof(Reference);
13.38 }
13.39
13.40 + void visitImportable(Object *obj) {
13.41 + visitField(obj, Package::offsetOfName());
13.42 + visitField(obj, Package::offsetOfParent());
13.43 + visitField(obj, Package::offsetOfPath());
13.44 + }
13.45 +
13.46 size_t iterateModule(Object *obj) {
13.47 - visitField(obj, Module::offsetOfFile());
13.48 + visitImportable(obj);
13.49 visitField(obj, Module::offsetOfGlobals());
13.50 visitField(obj, Module::offsetOfCode());
13.51 return sizeof(Module);
13.52 }
13.53
13.54 + size_t iteratePackage(Object *obj) {
13.55 + visitImportable(obj);
13.56 + visitField(obj, Package::offsetOfContents());
13.57 + return sizeof(Package);
13.58 + }
13.59 +
13.60 size_t iterateFunction(Object *obj) {
13.61 visitField(obj, Function::offsetOfCode());
13.62 visitField(obj, Function::offsetOfType());
13.63 @@ -202,6 +216,11 @@
13.64 return obj->objSize();
13.65 }
13.66
13.67 + size_t iterateList(Object *obj) {
13.68 + visitField(obj, List<Object>::offsetOfArray());
13.69 + return sizeof(List<Object>);
13.70 + }
13.71 +
13.72 private:
13.73 size_t iterateObject(Object *obj) {
13.74 visitField(obj, Object::offsetOfMap());
13.75 @@ -243,6 +262,9 @@
13.76 case MapKind_Module:
13.77 return iterateModule(obj);
13.78
13.79 + case MapKind_Package:
13.80 + return iteratePackage(obj);
13.81 +
13.82 case MapKind_Function:
13.83 return iterateFunction(obj);
13.84
13.85 @@ -264,6 +286,9 @@
13.86 case MapKind_Struct:
13.87 return iterateStruct(Struct::cast(obj));
13.88
13.89 + case MapKind_List:
13.90 + return iterateList(obj);
13.91 +
13.92 case MapKind_EnvironmentSlotDescriptorArray:
13.93 return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
13.94
13.95 @@ -335,6 +360,9 @@
13.96 case MapKind_Module:
13.97 return sizeof(Module);
13.98
13.99 + case MapKind_Package:
13.100 + return sizeof(Package);
13.101 +
13.102 case MapKind_Descriptor:
13.103 return sizeof(Descriptor);
13.104
13.105 @@ -356,6 +384,9 @@
13.106 case MapKind_Box:
13.107 return sizeof(Box);
13.108
13.109 + case MapKind_List:
13.110 + return sizeof(List<Object>);
13.111 +
13.112 case MapKind_Struct:
13.113 return Struct::cast(obj)->objSize();
13.114
14.1 --- a/src/Objects.h Sat Dec 29 00:55:38 2012 -0800
14.2 +++ b/src/Objects.h Tue Jan 01 15:34:07 2013 -0800
14.3 @@ -2,19 +2,19 @@
14.4 *
14.5 * Copyright (C) 2012 David Anderson
14.6 *
14.7 - * This file is part of JITCraft.
14.8 + * This file is part of SourcePawn.
14.9 *
14.10 - * JITCraft is free software: you can redistribute it and/or modify it under
14.11 + * SourcePawn is free software: you can redistribute it and/or modify it under
14.12 * the terms of the GNU General Public License as published by the Free
14.13 * Software Foundation, either version 3 of the License, or (at your option)
14.14 * any later version.
14.15 *
14.16 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
14.17 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
14.18 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14.19 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14.20 *
14.21 * You should have received a copy of the GNU General Public License along with
14.22 - * JITCraft. If not, see http://www.gnu.org/licenses/.
14.23 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
14.24 */
14.25 #ifndef _include_jitcraft_objects_h_
14.26 #define _include_jitcraft_objects_h_
14.27 @@ -57,6 +57,8 @@
14.28 MapKind_Environment,
14.29 MapKind_Descriptor,
14.30 MapKind_Box,
14.31 + MapKind_Package,
14.32 + MapKind_List,
14.33
14.34 // These do not have canonical maps.
14.35 MapKind_Array,
14.36 @@ -92,6 +94,10 @@
14.37
14.38 inline void write(Zone *zone, Object **ptr, Object *value);
14.39
14.40 + static inline Object *cast(Object *obj) {
14.41 + return obj;
14.42 + }
14.43 +
14.44 static inline size_t offsetOfMap() {
14.45 // Clang doesn't accept offsetof here and it's not clear why...
14.46 return reinterpret_cast<size_t>(&((Object *)NULL)->map_);
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/src/Packages.cpp Tue Jan 01 15:34:07 2013 -0800
15.3 @@ -0,0 +1,219 @@
15.4 +/*
15.5 + * Copyright (C) 2012 David Anderson
15.6 + *
15.7 + * This file is part of SourcePawn.
15.8 + *
15.9 + * SourcePawn is free software: you can redistribute it and/or modify it under
15.10 + * the terms of the GNU General Public License as published by the Free
15.11 + * Software Foundation, either version 3 of the License, or (at your option)
15.12 + * any later version.
15.13 + *
15.14 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
15.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15.17 + *
15.18 + * You should have received a copy of the GNU General Public License along with
15.19 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
15.20 + */
15.21 +#include "Zone.h"
15.22 +#include "Heap.h"
15.23 +#include "Strings.h"
15.24 +#include "Modules.h"
15.25 +#include "Packages.h"
15.26 +#include "FileSystem.h"
15.27 +#include "List.h"
15.28 +#include "Heap-inl.h"
15.29 +#include "Handles-inl.h"
15.30 +
15.31 +using namespace ke;
15.32 +
15.33 +Package *
15.34 +Package::NewNormalized(Zone *zone, Handle<Package> parent, Handle<String> path, Handle<String> name, unsigned flags)
15.35 +{
15.36 + Local<Package> package(zone, Package::cast(zone->allocate(MapKind_Package, sizeof(Package), Heap::Tenure_Old)));
15.37 + if (!package)
15.38 + return NULL;
15.39 +
15.40 + // :TODO: assert path, name are atoms.
15.41 +
15.42 + package->flags_ = flags;
15.43 + package->name_ = name;
15.44 + package->parent_ = parent;
15.45 + package->path_ = path;
15.46 + package->nativeIdentity_ = parent ? parent->getNativeIdentity() : NULL;
15.47 +
15.48 + return package;
15.49 +}
15.50 +
15.51 +Package *
15.52 +Package::New(Zone *zone, Handle<Package> parent, const char *path, Handle<String> name, unsigned flags)
15.53 +{
15.54 + Local<String> strpath(zone, zone->makeSymbol(path));
15.55 + if (!strpath)
15.56 + return NULL;
15.57 +
15.58 + return Package::NewNormalized(zone, parent, strpath, name, flags);
15.59 +}
15.60 +
15.61 +bool
15.62 +Package::add(Zone *zone, Handle<Importable> obj)
15.63 +{
15.64 + Local<Package> pkg(zone, this);
15.65 +
15.66 + assert(obj->parent() == pkg);
15.67 +
15.68 + if (!pkg->contents_) {
15.69 + pkg->contents_ = List<Importable>::New(zone);
15.70 + if (!pkg->contents_)
15.71 + return false;
15.72 + }
15.73 +
15.74 + if (!pkg->contents_->append(zone, obj))
15.75 + return false;
15.76 +
15.77 + return true;
15.78 +}
15.79 +
15.80 +Importable *
15.81 +Package::import(Handle<String> name)
15.82 +{
15.83 + if (!contents_)
15.84 + return NULL;
15.85 +
15.86 + for (unsigned i = 0; i < contents_->length(); i++) {
15.87 + Importable *obj = contents_->at(i);
15.88 + if (obj->isPackage() && Package::cast(obj)->name() == name)
15.89 + return obj;
15.90 + if (obj->isModule() && Module::cast(obj)->name() == name)
15.91 + return obj;
15.92 + }
15.93 +
15.94 + return NULL;
15.95 +}
15.96 +
15.97 +PackageCache::PackageCache(Zone *zone)
15.98 + : zone_(zone)
15.99 +{
15.100 +}
15.101 +
15.102 +bool
15.103 +PackageCache::initialize()
15.104 +{
15.105 + return true;
15.106 +}
15.107 +
15.108 +void
15.109 +PackageCache::accept(VirtualObjectVisitor *visitor)
15.110 +{
15.111 + for (size_t i = 0; i < roots_.length(); i++)
15.112 + visitor->visit(roots_[i].address());
15.113 +}
15.114 +
15.115 +bool
15.116 +PackageCache::checkfs(Handle<Package> package, PathComponent *path, Importable **out)
15.117 +{
15.118 + AutoFree<char> left(strdup(package->path()->chars()));
15.119 + AutoFree<char> right(strdup(path->name->chars()));
15.120 + AutoFree<char> result;
15.121 +
15.122 + if (!JoinPaths(zone_, result, *left, *right))
15.123 + return false;
15.124 +
15.125 + OS::PathType type = OS::InspectPath(*result);
15.126 + if (type == OS::Path_Folder) {
15.127 + // If there is a folder matching this path, create a new subpackage,
15.128 + // and then either return it (if this is the last link), or keep
15.129 + // trying to import the rest of the path.
15.130 + Local<String> strpath(zone_, zone_->makeSymbol(*result));
15.131 + Local<Package> subpackage(zone_, Package::NewNormalized(zone_, package, strpath, path->name, Package::Normal));
15.132 + if (!subpackage)
15.133 + return false;
15.134 + if (!path->next) {
15.135 + *out = subpackage;
15.136 + return true;
15.137 + }
15.138 + return import(subpackage, path->next, out);
15.139 + }
15.140 +
15.141 + // Otherwise, look for a file ending in ".sp".
15.142 + AutoFree<char> filepath((char *)zone_->malloc(strlen(*result) + strlen(".sp") + 1));
15.143 + if (!*filepath)
15.144 + return false;
15.145 +
15.146 + strcpy(*filepath, *result);
15.147 + strcat(*filepath, ".sp");
15.148 +
15.149 + type = OS::InspectPath(*filepath);
15.150 + if (type != OS::Path_File)
15.151 + return true;
15.152 +
15.153 + // Create a new, empty module.
15.154 + Local<String> strpath(zone_, zone_->makeSymbol(*filepath));
15.155 + if (!strpath)
15.156 + return false;
15.157 +
15.158 + Local<Module> module(zone_, Module::New(zone_, package, strpath, path->name));
15.159 + if (!module || !package->add(zone_, module))
15.160 + return false;
15.161 +
15.162 + *out = module;
15.163 + return true;
15.164 +}
15.165 +
15.166 +bool
15.167 +PackageCache::import(Handle<Package> package, PathComponent *path, Importable **out)
15.168 +{
15.169 + // If the package is jailed, none of its imports are visible.
15.170 + if (package->jailed())
15.171 + return true;
15.172 +
15.173 + Local<Importable> obj(zone_, package->import(path->name));
15.174 + if (!obj) {
15.175 + // We couldn't find anything. Try the file system.
15.176 + if (!checkfs(package, path, out))
15.177 + return false;
15.178 +
15.179 + // checkfs will keep trying to import, so if it fails, we just
15.180 + // propagate up.
15.181 + return true;
15.182 + }
15.183 +
15.184 + // If we found an existing module, or the path has no next link, then
15.185 + // we can't go any further.
15.186 + if (obj->is(MapKind_Module) || !path->next) {
15.187 + *out = obj;
15.188 + return true;
15.189 + }
15.190 +
15.191 + Local<Package> subpackage(zone_, Package::cast(obj));
15.192 + return import(subpackage, path->next, out);
15.193 +}
15.194 +
15.195 +bool
15.196 +PackageCache::findOrAdd(Handle<Package> package, PathComponent *path, Importable **out)
15.197 +{
15.198 + // Local rooters should have initialized this, but whatever.
15.199 + assert(*out == NULL);
15.200 +
15.201 + // Try to import locally first.
15.202 + if (!import(package, path, out))
15.203 + return false;
15.204 + if (*out)
15.205 + return true;
15.206 +
15.207 + // Otherwise, search system roots.
15.208 + Local<Package> root(zone_);
15.209 + for (size_t i = 0; i < roots_.length(); i++) {
15.210 + root = roots_[i];
15.211 + if (!import(root, path, out))
15.212 + return false;
15.213 + if (*out)
15.214 + return true;
15.215 + }
15.216 +
15.217 + return true;
15.218 +}
15.219 +
15.220 +PackageCache::~PackageCache()
15.221 +{
15.222 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/src/Packages.h Tue Jan 01 15:34:07 2013 -0800
16.3 @@ -0,0 +1,193 @@
16.4 +/*
16.5 + * Copyright (C) 2012 David Anderson
16.6 + *
16.7 + * This file is part of SourcePawn.
16.8 + *
16.9 + * SourcePawn is free software: you can redistribute it and/or modify it under
16.10 + * the terms of the GNU General Public License as published by the Free
16.11 + * Software Foundation, either version 3 of the License, or (at your option)
16.12 + * any later version.
16.13 + *
16.14 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
16.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16.17 + *
16.18 + * You should have received a copy of the GNU General Public License along with
16.19 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
16.20 + */
16.21 +#ifndef _include_sp2_packages_h_
16.22 +#define _include_sp2_packages_h_
16.23 +
16.24 +#include "PoolAllocator.h"
16.25 +#include "Objects.h"
16.26 +#include "HashTable.h"
16.27 +
16.28 +namespace ke {
16.29 +
16.30 +class String;
16.31 +class Module;
16.32 +class Package;
16.33 +class ImportStatement;
16.34 +class VirtualObjectVisitor;
16.35 +
16.36 +template <typename T> class List;
16.37 +
16.38 +struct PathComponent : PoolObject
16.39 +{
16.40 + PathComponent(ScopedRoot<String> *name, PathComponent *next)
16.41 + : name(*name),
16.42 + next(next)
16.43 + {
16.44 + }
16.45 + ScopedRoot<String> &name;
16.46 + PathComponent *next;
16.47 +};
16.48 +
16.49 +class Importable : public Object
16.50 +{
16.51 + public:
16.52 + Package *parent() {
16.53 + return parent_;
16.54 + }
16.55 + String *path() {
16.56 + return path_;
16.57 + }
16.58 + String *name() {
16.59 + return name_;
16.60 + }
16.61 +
16.62 + bool isModule() {
16.63 + return is(MapKind_Module);
16.64 + }
16.65 + bool isPackage() {
16.66 + return is(MapKind_Package);
16.67 + }
16.68 +
16.69 + static inline size_t offsetOfName() {
16.70 + return OFFSETOF(Importable, name_);
16.71 + }
16.72 + static inline size_t offsetOfParent() {
16.73 + return OFFSETOF(Importable, parent_);
16.74 + }
16.75 + static inline size_t offsetOfPath() {
16.76 + return OFFSETOF(Importable, path_);
16.77 + }
16.78 +
16.79 + static inline Importable *cast(Object *obj) {
16.80 + assert(!obj || obj->is(MapKind_Module) || obj->is(MapKind_Package));
16.81 + return reinterpret_cast<Importable *>(obj);
16.82 + }
16.83 +
16.84 + protected:
16.85 + Barriered<String> name_;
16.86 + Barriered<Package> parent_;
16.87 + Barriered<String> path_;
16.88 +};
16.89 +
16.90 +// A package is a single folder in the file system, and contains any number of
16.91 +// modules and sub-packages. The package hierarchy forms a tree. For simplicity
16.92 +// the root of the tree is an anonymous package that contains no modules.
16.93 +//
16.94 +// Each package in the package hierarchy has two components of path information:
16.95 +// (1) Canonical path. This is a normalized path used to compute the paths of
16.96 +// modules.
16.97 +// (2) Name. This is the package's name as it would appear in a path
16.98 +// component. It is optional.
16.99 +//
16.100 +// Packages may be "hidden", meaning that even if they have names, their name
16.101 +// is not accessible from any import statements. Packages may also be "jailed",
16.102 +// meaning that other names in the package are not visible to each other.
16.103 +//
16.104 +// Packages are created in a few ways:
16.105 +//
16.106 +// (1) System Roots. A system root is a default search location for imports,
16.107 +// and they are installed at the top-level of the hierarchy by the host
16.108 +// application. A system root has a unique top-level name and path.
16.109 +// System roots are always hidden.
16.110 +//
16.111 +// (2) Imports. When importing, the package hierarchy may be extended as
16.112 +// new paths are discovered. Packages discovered this way are never
16.113 +// hidden or jailed.
16.114 +//
16.115 +// (3) Via Package::New(), which creates an empty package. This can be used
16.116 +// to create custom packages.
16.117 +class Package : public Importable
16.118 +{
16.119 + public:
16.120 + enum {
16.121 + Normal = 0,
16.122 +
16.123 + // These must match the flags in the public API for Package.
16.124 + Hidden = (1 << 0),
16.125 + Jailed = (1 << 1)
16.126 + };
16.127 +
16.128 + public:
16.129 + static Package *NewNormalized(Zone *zone,
16.130 + Handle<Package> parent,
16.131 + Handle<String> path,
16.132 + Handle<String> name,
16.133 + unsigned flags);
16.134 + static Package *New(Zone *zone,
16.135 + Handle<Package> parent,
16.136 + const char *path,
16.137 + Handle<String> name,
16.138 + unsigned flags);
16.139 +
16.140 + bool add(Zone *zone, Handle<Importable> component);
16.141 +
16.142 + bool hidden() {
16.143 + return !!(flags_ & Package::Hidden);
16.144 + }
16.145 + bool jailed() {
16.146 + return !!(flags_ & Package::Jailed);
16.147 + }
16.148 +
16.149 + void setNativeIdentity(void *identity) {
16.150 + nativeIdentity_ = identity;
16.151 + }
16.152 + void *getNativeIdentity() {
16.153 + return nativeIdentity_;
16.154 + }
16.155 + Importable *import(Handle<String> name);
16.156 +
16.157 + // Begin GC descriptor.
16.158 + static inline size_t offsetOfContents() {
16.159 + return OFFSETOF(Package, contents_);
16.160 + }
16.161 + // End GC descriptor.
16.162 +
16.163 + static inline Package *cast(Object *obj) {
16.164 + assert(!obj || obj->is(MapKind_Package));
16.165 + return reinterpret_cast<Package *>(obj);
16.166 + }
16.167 +
16.168 + private:
16.169 + unsigned flags_;
16.170 + Barriered<List<Importable> > contents_;
16.171 + void *nativeIdentity_;
16.172 +};
16.173 +
16.174 +class PackageCache
16.175 +{
16.176 + public:
16.177 + PackageCache(Zone *zone);
16.178 + ~PackageCache();
16.179 + bool initialize();
16.180 +
16.181 + bool findOrAdd(Handle<Package> package, PathComponent *path, Importable **out);
16.182 +
16.183 + void accept(VirtualObjectVisitor *visitor);
16.184 +
16.185 + private:
16.186 + bool import(Handle<Package> package, PathComponent *path, Importable **out);
16.187 + bool checkfs(Handle<Package> package, PathComponent *path, Importable **out);
16.188 +
16.189 + private:
16.190 + Zone *zone_;
16.191 + Vector<Unbarriered<Package> > roots_;
16.192 +};
16.193 +
16.194 +} // namespace ke
16.195 +
16.196 +#endif // _include_sp2_packages_h_
17.1 --- a/src/Platform-Posix.cpp Sat Dec 29 00:55:38 2012 -0800
17.2 +++ b/src/Platform-Posix.cpp Tue Jan 01 15:34:07 2013 -0800
17.3 @@ -17,6 +17,9 @@
17.4 * JITCraft. If not, see http://www.gnu.org/licenses/.
17.5 */
17.6 #include <sys/mman.h>
17.7 +#include <limits.h>
17.8 +#include <string.h>
17.9 +#include <stdlib.h>
17.10 #include "Platform.h"
17.11
17.12 using namespace ke;
17.13 @@ -99,3 +102,55 @@
17.14 OS::UnmapMemory(address, size);
17.15 }
17.16
17.17 +bool
17.18 +OS::GetAbsolutePath(const char *path, AutoFree<char> &chars)
17.19 +{
17.20 + chars = (char *)calloc(PATH_MAX, sizeof(char));
17.21 + if (!*chars)
17.22 + return false;
17.23 +
17.24 + char *ptr = realpath(path, *chars);
17.25 + if (!ptr)
17.26 + return false;
17.27 +
17.28 + return ptr == *chars;
17.29 +}
17.30 +
17.31 +bool
17.32 +OS::SplitPath(const char *path, AutoFree<char> &base, AutoFree<char> &name)
17.33 +{
17.34 + // dirname() and basename() pretty much suck.
17.35 + size_t len = strlen(path);
17.36 +
17.37 + // Skip trailing slashes.
17.38 + while (len > 1 && (path[len - 1] == '/'))
17.39 + len--;
17.40 +
17.41 + for (size_t i = len - 1; i < len; i--) {
17.42 + if (path[i] == '/') {
17.43 + name = (char *)calloc(len - i, sizeof(char));
17.44 + if (!*name)
17.45 + return false;
17.46 +
17.47 + strcpy(*name, &path[i + 1]);
17.48 +
17.49 + base = (char *)calloc(i + 1, sizeof(char));
17.50 + if (!*base)
17.51 + return false;
17.52 +
17.53 + memcpy(*base, path, i);
17.54 + (*base)[i] = '\0';
17.55 + return true;
17.56 + }
17.57 + }
17.58 +
17.59 + // The path should have been absolute, which contains at least one separator.
17.60 + return false;
17.61 +}
17.62 +
17.63 +const char *
17.64 +OS::PathSeparator()
17.65 +{
17.66 + return "/";
17.67 +}
17.68 +
18.1 --- a/src/Platform-Windows.cpp Sat Dec 29 00:55:38 2012 -0800
18.2 +++ b/src/Platform-Windows.cpp Tue Jan 01 15:34:07 2013 -0800
18.3 @@ -17,9 +17,10 @@
18.4 * SourcePawn. If not, see http://www.gnu.org/licenses/.
18.5 */
18.6
18.7 -// :TODO: move into utility-style include
18.8 #define WIN32_LEAN_AND_MEAN
18.9 #include <Windows.h>
18.10 +#include <direct.h>
18.11 +#include <sys/stat.h>
18.12 #include "Platform.h"
18.13
18.14 using namespace ke;
18.15 @@ -109,3 +110,78 @@
18.16 {
18.17 OS::UnmapMemory(address, size);
18.18 }
18.19 +
18.20 +bool
18.21 +OS::GetAbsolutePath(const char *path, AutoFree<char> &chars)
18.22 +{
18.23 + char try1[MAX_PATH];
18.24 + DWORD result = GetFullPathName(path, sizeof(try1), try1, NULL);
18.25 + if (result <= 0)
18.26 + return false;
18.27 +
18.28 + // +1 because if result < MAX_PATH, it doesn't include the null terminator.
18.29 + chars = (char *)calloc(result + 1, sizeof(char));
18.30 + if (!*chars)
18.31 + return false;
18.32 +
18.33 + if (result <= MAX_PATH) {
18.34 + strcpy(*chars, try1);
18.35 + return true;
18.36 + }
18.37 +
18.38 + // We should get the same output on the next try.
18.39 + return GetFullPathName(path, result, *chars, NULL) == result - 1;
18.40 +}
18.41 +
18.42 +bool
18.43 +OS::SplitPath(const char *path, AutoFree<char> &base, AutoFree<char> &name)
18.44 +{
18.45 + size_t len = strlen(path);
18.46 +
18.47 + // Skip trailing slashes.
18.48 + while (len > 1 && (path[len - 1] == '/' || path[len - 1] == '\\'))
18.49 + len--;
18.50 +
18.51 + for (size_t i = len - 1; i < len; i--) {
18.52 + if (path[i] == '\\' || path[i] == '/') {
18.53 + name = (char *)calloc(len - i, sizeof(char));
18.54 + if (!*name)
18.55 + return false;
18.56 +
18.57 + strcpy(*name, &path[i + 1]);
18.58 +
18.59 + base = (char *)calloc(i + 1, sizeof(char));
18.60 + if (!*base)
18.61 + return false;
18.62 +
18.63 + memcpy(*base, path, i);
18.64 + (*base)[i] = '\0';
18.65 + return true;
18.66 + }
18.67 + }
18.68 +
18.69 + // The path should have been absolute, which contains at least one separator.
18.70 + return false;
18.71 +}
18.72 +
18.73 +const char *
18.74 +OS::PathSeparator()
18.75 +{
18.76 + return "\\";
18.77 +}
18.78 +
18.79 +OS::PathType
18.80 +OS::InspectPath(const char *path)
18.81 +{
18.82 + struct _stat s;
18.83 + int result = _stat(path, &s);
18.84 + if (result != 0)
18.85 + return OS::Path_Invalid;
18.86 +
18.87 + if (s.st_mode & _S_IFDIR)
18.88 + return OS::Path_Folder;
18.89 + if (s.st_mode & _S_IFREG)
18.90 + return OS::Path_File;
18.91 +
18.92 + return OS::Path_Invalid;
18.93 +}
19.1 --- a/src/Platform.h Sat Dec 29 00:55:38 2012 -0800
19.2 +++ b/src/Platform.h Tue Jan 01 15:34:07 2013 -0800
19.3 @@ -2,19 +2,19 @@
19.4 *
19.5 * Copyright (C) 2012 David Anderson
19.6 *
19.7 - * This file is part of JITCraft.
19.8 + * This file is part of SourcePawn.
19.9 *
19.10 - * JITCraft is free software: you can redistribute it and/or modify it under
19.11 + * SourcePawn is free software: you can redistribute it and/or modify it under
19.12 * the terms of the GNU General Public License as published by the Free
19.13 * Software Foundation, either version 3 of the License, or (at your option)
19.14 * any later version.
19.15 *
19.16 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
19.17 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
19.18 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19.19 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19.20 *
19.21 * You should have received a copy of the GNU General Public License along with
19.22 - * JITCraft. If not, see http://www.gnu.org/licenses/.
19.23 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
19.24 */
19.25 #ifndef _include_jitcraft_platform_h_
19.26 #define _include_jitcraft_platform_h_
19.27 @@ -72,10 +72,28 @@
19.28 }
19.29 };
19.30
19.31 + enum PathType {
19.32 + Path_Invalid,
19.33 + Path_File,
19.34 + Path_Folder
19.35 + };
19.36 +
19.37 + PathType InspectPath(const char *path);
19.38 +
19.39 + // Converts a relative path into an absolute path, based on the current
19.40 + // working directory.
19.41 + bool GetAbsolutePath(const char *path, AutoFree<char> &chars);
19.42 +
19.43 + // Splits a path into its constituent base folder and file. The path must
19.44 + // be an absolute path.
19.45 + bool SplitPath(const char *path, AutoFree<char> &base, AutoFree<char> &name);
19.46 +
19.47 // MapAlignedMemory is guaranteed to return zeroed memory.
19.48 AlignableMapping MapAlignedMemory(size_t amount, size_t alignment, MapMode mode);
19.49 void UnmapAlignedMemory(Address address, size_t size);
19.50
19.51 + const char *PathSeparator();
19.52 +
19.53 // The default alignment of memory returned via MapMemory().
19.54 // :TODO: better ifdefs
19.55 #ifdef _MSC_VER
20.1 --- a/src/Stack.cpp Sat Dec 29 00:55:38 2012 -0800
20.2 +++ b/src/Stack.cpp Tue Jan 01 15:34:07 2013 -0800
20.3 @@ -328,8 +328,8 @@
20.4 {
20.5 if (fp_->isNative())
20.6 return "<native>";
20.7 - return fp_->code()->module()->file()
20.8 - ? fp_->code()->module()->file()->chars()
20.9 + return fp_->code()->module()->path()
20.10 + ? fp_->code()->module()->path()->chars()
20.11 : "(anonymous)";
20.12 }
20.13
21.1 --- a/src/Strings.h Sat Dec 29 00:55:38 2012 -0800
21.2 +++ b/src/Strings.h Tue Jan 01 15:34:07 2013 -0800
21.3 @@ -38,6 +38,9 @@
21.4 char *chars() {
21.5 return reinterpret_cast<char *>(this + 1);
21.6 }
21.7 + char *chars(Zone *zone) {
21.8 + return chars();
21.9 + }
21.10 size_t objSize() {
21.11 return SizeFor(length());
21.12 }
22.1 --- a/src/Utility.h Sat Dec 29 00:55:38 2012 -0800
22.2 +++ b/src/Utility.h Tue Jan 01 15:34:07 2013 -0800
22.3 @@ -21,6 +21,7 @@
22.4
22.5 #include <assert.h>
22.6 #include <stddef.h>
22.7 +#include <stdlib.h>
22.8 #include "../include/keima_util.h"
22.9 #ifdef _MSC_VER
22.10 # include <intrin.h>
22.11 @@ -47,28 +48,33 @@
22.12 static const size_t kGB = 1024 * kMB;
22.13
22.14 template <typename T>
22.15 -class AutoVec
22.16 +class AutoFree
22.17 {
22.18 T *t_;
22.19
22.20 public:
22.21 - AutoVec()
22.22 + AutoFree()
22.23 : t_(NULL)
22.24 {
22.25 }
22.26 - AutoVec(T *t)
22.27 + AutoFree(T *t)
22.28 : t_(t)
22.29 {
22.30 }
22.31 - ~AutoVec() {
22.32 - delete [] t_;
22.33 + ~AutoFree() {
22.34 + free(t_);
22.35 }
22.36 - operator T *() {
22.37 + T *take() {
22.38 + T *t = t_;
22.39 + t_ = NULL;
22.40 + return t;
22.41 + }
22.42 + T *operator *() const {
22.43 return t_;
22.44 }
22.45 void operator =(T *t) {
22.46 if (t_)
22.47 - delete [] t_;
22.48 + free(t_);
22.49 t_ = t;
22.50 }
22.51 };
22.52 @@ -116,11 +122,11 @@
22.53 static inline uint32
22.54 HashInt32(int32 a)
22.55 {
22.56 - a = (a ^ 61) ^ (a >> 16);
22.57 - a = a + (a << 3);
22.58 - a = a ^ (a >> 4);
22.59 - a = a * 0x27d4eb2d;
22.60 - a = a ^ (a >> 15);
22.61 + a = (a ^ 61) ^ (a >> 16);
22.62 + a = a + (a << 3);
22.63 + a = a ^ (a >> 4);
22.64 + a = a * 0x27d4eb2d;
22.65 + a = a ^ (a >> 15);
22.66 return a;
22.67 }
22.68
22.69 @@ -128,12 +134,12 @@
22.70 static inline uint32
22.71 HashInt64(int64 key)
22.72 {
22.73 - key = (~key) + (key << 18); // key = (key << 18) - key - 1;
22.74 - key = key ^ (uint64(key) >> 31);
22.75 - key = key * 21; // key = (key + (key << 2)) + (key << 4);
22.76 - key = key ^ (uint64(key) >> 11);
22.77 - key = key + (key << 6);
22.78 - key = key ^ (uint64(key) >> 22);
22.79 + key = (~key) + (key << 18); // key = (key << 18) - key - 1;
22.80 + key = key ^ (uint64(key) >> 31);
22.81 + key = key * 21; // key = (key + (key << 2)) + (key << 4);
22.82 + key = key ^ (uint64(key) >> 11);
22.83 + key = key + (key << 6);
22.84 + key = key ^ (uint64(key) >> 22);
22.85 return uint32(key);
22.86 }
22.87
22.88 @@ -161,11 +167,11 @@
22.89 # endif
22.90 return rval;
22.91 #else
22.92 - size_t bit;
22.93 - asm("bsr %1, %0\n"
22.94 - : "=r" (bit)
22.95 - : "rm" (number));
22.96 - return bit;
22.97 + size_t bit;
22.98 + asm("bsr %1, %0\n"
22.99 + : "=r" (bit)
22.100 + : "rm" (number));
22.101 + return bit;
22.102 #endif
22.103 }
22.104
22.105 @@ -183,11 +189,11 @@
22.106 # endif
22.107 return rval;
22.108 #else
22.109 - size_t bit;
22.110 - asm("bsf %1, %0\n"
22.111 - : "=r" (bit)
22.112 - : "rm" (number));
22.113 - return bit;
22.114 + size_t bit;
22.115 + asm("bsf %1, %0\n"
22.116 + : "=r" (bit)
22.117 + : "rm" (number));
22.118 + return bit;
22.119 #endif
22.120 }
22.121
22.122 @@ -253,7 +259,7 @@
22.123 #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
22.124 #define STATIC_ASSERT(cond) extern int static_assert_f(int a[(cond) ? 1 : -1])
22.125
22.126 -#define IS_ALIGNED(addr, alignment) (!(uintptr_t(addr) & ((alignment) - 1)))
22.127 +#define IS_ALIGNED(addr, alignment) (!(uintptr_t(addr) & ((alignment) - 1)))
22.128
22.129 template <typename T>
22.130 static inline bool
23.1 --- a/src/Vector.h Sat Dec 29 00:55:38 2012 -0800
23.2 +++ b/src/Vector.h Tue Jan 01 15:34:07 2013 -0800
23.3 @@ -106,8 +106,7 @@
23.4 }
23.5 if (maxsize == 0)
23.6 maxsize = 8;
23.7 - while (nitems + needed > maxsize)
23.8 - {
23.9 + while (nitems + needed > maxsize) {
23.10 if (!IsUintPtrMultiplySafe(maxsize, 2)) {
23.11 this->reportAllocationOverflow();
23.12 return false;
23.13 @@ -117,8 +116,7 @@
23.14 T* newdata = (T*)this->malloc(sizeof(T) * maxsize);
23.15 if (newdata == NULL)
23.16 return false;
23.17 - for (size_t i = 0; i < nitems; i++)
23.18 - {
23.19 + for (size_t i = 0; i < nitems; i++) {
23.20 new (&newdata[i]) T(data[i]);
23.21 data[i].~T();
23.22 }
24.1 --- a/src/Zone.cpp Sat Dec 29 00:55:38 2012 -0800
24.2 +++ b/src/Zone.cpp Tue Jan 01 15:34:07 2013 -0800
24.3 @@ -24,6 +24,7 @@
24.4 #include "AllocatorPolicies.h"
24.5 #include "Array.h"
24.6 #include "NativeTable.h"
24.7 +#include "Packages.h"
24.8 #include "Spaces-inl.h"
24.9 #include "Heap-inl.h"
24.10
24.11 @@ -39,6 +40,8 @@
24.12 types_(NULL),
24.13 symbols_(NULL),
24.14 globalRoots_(NULL),
24.15 + nativeTable_(NULL),
24.16 + packages_(NULL),
24.17 lastLocalRoot_(NULL),
24.18 specialRoots_(NULL),
24.19 hasPendingException_(false),
24.20 @@ -48,10 +51,11 @@
24.21
24.22 Zone::~Zone()
24.23 {
24.24 + delete nativeTable_;
24.25 delete types_;
24.26 - delete nativeTable_;
24.27 + delete symbols_;
24.28 + delete packages_;
24.29 delete globalRoots_;
24.30 - delete symbols_;
24.31 }
24.32
24.33 bool
24.34 @@ -74,6 +78,10 @@
24.35 if (!nativeTable_ || !nativeTable_->initialize())
24.36 return false;
24.37
24.38 + packages_ = new PackageCache(this);
24.39 + if (!packages_ || !packages_->initialize())
24.40 + return false;
24.41 +
24.42 MapKind maps[] =
24.43 {
24.44 MapKind_Type,
24.45 @@ -95,6 +103,8 @@
24.46 MapKind_Native,
24.47 MapKind_Descriptor,
24.48 MapKind_Box,
24.49 + MapKind_List,
24.50 + MapKind_Package,
24.51 MapKind_FreeRegion,
24.52 MapKind_EnvironmentSlotDescriptorArray
24.53 };
24.54 @@ -176,6 +186,7 @@
24.55 globalRoots_->accept(visitor);
24.56 rootScopes_.accept(visitor);
24.57 nativeTable_->accept(visitor);
24.58 + packages_->accept(visitor);
24.59
24.60 stack_.accept(visitor);
24.61 }
24.62 @@ -326,6 +337,24 @@
24.63 publicFunctionListener_ = listener;
24.64 }
24.65
24.66 +void *
24.67 +Zone::malloc(size_t size)
24.68 +{
24.69 + void *ptr = ::malloc(size);
24.70 + if (!ptr)
24.71 + reportOutOfMemory();
24.72 + return ptr;
24.73 +}
24.74 +
24.75 +void *
24.76 +Zone::realloc(void *ptr, size_t size)
24.77 +{
24.78 + ptr = ::realloc(ptr, size);
24.79 + if (!ptr)
24.80 + reportOutOfMemory();
24.81 + return ptr;
24.82 +}
24.83 +
24.84 AutoRooted::AutoRooted(Zone *zone)
24.85 : zone_(zone),
24.86 prev_(*zone->lastSpecialRoot())
25.1 --- a/src/Zone.h Sat Dec 29 00:55:38 2012 -0800
25.2 +++ b/src/Zone.h Tue Jan 01 15:34:07 2013 -0800
25.3 @@ -38,6 +38,7 @@
25.4 class ArrayMap;
25.5 class Exception;
25.6 class NativeTable;
25.7 +class PackageCache;
25.8
25.9 class Zone
25.10 {
25.11 @@ -54,6 +55,7 @@
25.12 StringPool *symbols_;
25.13 GlobalRoots *globalRoots_;
25.14 NativeTable *nativeTable_;
25.15 + PackageCache *packages_;
25.16
25.17 // Root list.
25.18 Local<Object> *lastLocalRoot_;
25.19 @@ -129,6 +131,9 @@
25.20 NativeTable *nativeTable() {
25.21 return nativeTable_;
25.22 }
25.23 + PackageCache *packages() {
25.24 + return packages_;
25.25 + }
25.26
25.27 String *makeSymbol(const char *string, size_t length);
25.28 String *makeSymbol(const char *string);
25.29 @@ -150,6 +155,10 @@
25.30 void setPublicFunctionListener(Ke::IPublicFunctionListener *listener);
25.31 void registerPublic(Handle<Function> fun);
25.32 void unregisterPublic(Handle<Function> fun);
25.33 +
25.34 + // Helpers that report OOM.
25.35 + void *malloc(size_t size);
25.36 + void *realloc(void *ptr, size_t size);
25.37 };
25.38
25.39 // In a multi-threaded system, this would be a TLS variable.
26.1 --- a/src/compiler/AST.h Sat Dec 29 00:55:38 2012 -0800
26.2 +++ b/src/compiler/AST.h Tue Jan 01 15:34:07 2013 -0800
26.3 @@ -28,6 +28,7 @@
26.4 namespace ke {
26.5
26.6 class Scope;
26.7 +struct PathComponent;
26.8
26.9 #define ASTKINDS(_) \
26.10 _(VariableDeclaration) \
26.11 @@ -58,7 +59,7 @@
26.12 _(StructureStatement) \
26.13 _(SwitchStatement) \
26.14 _(ArrayLiteral) \
26.15 - _(ImportStatement)
26.16 + _(ImportStatement)
26.17
26.18 // Forward declarations.
26.19 #define _(name) class name;
26.20 @@ -1104,9 +1105,9 @@
26.21 class ImportStatement : public Statement
26.22 {
26.23 public:
26.24 - ImportStatement(const SourcePosition &pos, NameList *names, TokenKind suffix)
26.25 + ImportStatement(const SourcePosition &pos, PathComponent *path, TokenKind suffix)
26.26 : Statement(pos),
26.27 - names_(names),
26.28 + path_(path),
26.29 suffix_(suffix),
26.30 source_(NULL)
26.31 {
26.32 @@ -1114,8 +1115,8 @@
26.33
26.34 DECLARE_NODE(ImportStatement);
26.35
26.36 - NameList *path() const {
26.37 - return names_;
26.38 + PathComponent *path() const {
26.39 + return path_;
26.40 }
26.41 void setImportSource(TranslationUnit *unit) {
26.42 source_ = unit;
26.43 @@ -1126,13 +1127,9 @@
26.44 TokenKind suffix() const {
26.45 return suffix_;
26.46 }
26.47 - Handle<String> name() const {
26.48 - assert(suffix() != TOK_STAR);
26.49 - return *names_->at(names_->length() - 1);
26.50 - }
26.51
26.52 private:
26.53 - NameList *names_;
26.54 + PathComponent *path_;
26.55 TokenKind suffix_;
26.56 TranslationUnit *source_;
26.57 };
27.1 --- a/src/compiler/CompileContext.cpp Sat Dec 29 00:55:38 2012 -0800
27.2 +++ b/src/compiler/CompileContext.cpp Tue Jan 01 15:34:07 2013 -0800
27.3 @@ -1,23 +1,25 @@
27.4 /*
27.5 * Copyright (C) 2012 David Anderson
27.6 *
27.7 - * This file is part of JITCraft.
27.8 + * This file is part of SourcePawn.
27.9 *
27.10 - * JITCraft is free software: you can redistribute it and/or modify it under
27.11 + * SourcePawn is free software: you can redistribute it and/or modify it under
27.12 * the terms of the GNU General Public License as published by the Free
27.13 * Software Foundation, either version 3 of the License, or (at your option)
27.14 * any later version.
27.15 *
27.16 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
27.17 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
27.18 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
27.19 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
27.20 *
27.21 * You should have received a copy of the GNU General Public License along with
27.22 - * JITCraft. If not, see http://www.gnu.org/licenses/.
27.23 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
27.24 */
27.25 #include <stdio.h>
27.26 #include "../Zone.h"
27.27 #include "../Interpreter.h"
27.28 +#include "../Packages.h"
27.29 +#include "../FileSystem.h"
27.30 #include "Scanner.h"
27.31 #include "CompileContext.h"
27.32 #include "Parser.h"
27.33 @@ -38,28 +40,57 @@
27.34 CompileContext::~CompileContext()
27.35 {
27.36 for (size_t i = 0; i < units_.length(); i++)
27.37 - delete units_[i];
27.38 + units_[i]->destroy();
27.39 }
27.40
27.41 bool
27.42 -CompileContext::addTranslationUnit(TranslationUnit *unit)
27.43 +CompileContext::initialize(Handle<Package> package, const char *name)
27.44 {
27.45 - if (!units_.append(unit))
27.46 + size_t len = strlen(name);
27.47 + AutoFree<char> path((char *)zone_->malloc(len + 1));
27.48 + if (!*path)
27.49 + return false;
27.50 +
27.51 + strcpy(*path, name);
27.52 + if (len > 3 && strcmp(&name[len - 3], ".sp") == 0)
27.53 + (*path)[len - 3] = '\0';
27.54 +
27.55 + Local<String> strname(zone_, zone_->makeSymbol(*path));
27.56 + if (!strname)
27.57 return false;
27.58
27.59 - if (!unparsed_.append(unit))
27.60 + PathComponent p(new ScopedRoot<String>(strname), NULL);
27.61 +
27.62 + Local<Importable> importable(zone_);
27.63 + if (!zone_->packages()->findOrAdd(package, &p, importable.address()))
27.64 + return false;
27.65 +
27.66 + // If we couldn't find anything on the filesystem to match, we error out
27.67 + // early.
27.68 + if (!importable) {
27.69 + zone_->reportError(Message_CannotImportPath, *path);
27.70 return false;
27.71 + }
27.72 +
27.73 + if (importable->isModule()) {
27.74 + Local<Module> module(zone_, Module::cast(importable));
27.75 + if (!add(module))
27.76 + return true;
27.77 + } else {
27.78 + // nyi
27.79 + assert(false);
27.80 + }
27.81
27.82 return true;
27.83 }
27.84
27.85 char *
27.86 -CompileContext::loadSource(const char *file, size_t *lengthp)
27.87 +CompileContext::loadSource(Handle<Module> module, size_t *lengthp)
27.88 {
27.89 char *bytes = NULL;
27.90 size_t length;
27.91
27.92 - FILE *fp = fopen(file, "rb");
27.93 + FILE *fp = fopen(module->path()->chars(), "rb");
27.94 if (!fp) {
27.95 reportError(SourcePosition(), Message_CantOpenFile);
27.96 return NULL;
27.97 @@ -94,12 +125,10 @@
27.98 bool
27.99 CompileContext::parse(TranslationUnit *unit)
27.100 {
27.101 - AutoEnterCompileContext enter(*this, unit);
27.102 -
27.103 assert(!unit->tree_);
27.104
27.105 size_t length;
27.106 - char *source = loadSource(unit->path_, &length);
27.107 + char *source = loadSource(unit->module(), &length);
27.108 if (!source)
27.109 return false;
27.110
27.111 @@ -110,26 +139,53 @@
27.112 return true;
27.113 }
27.114
27.115 -void
27.116 +bool
27.117 CompileContext::evaluateImports(TranslationUnit *unit)
27.118 {
27.119 - if (units_.length() > 1)
27.120 - return;
27.121 + PoolList<ImportStatement *> *imports = unit->tree()->imports();
27.122 +
27.123 + for (size_t i = 0; i < imports->length(); i++) {
27.124 + ImportStatement *import = imports->at(i);
27.125 +
27.126 + // Step 1. Crawl the path until we find a valid file to load.
27.127 + Local<Importable> obj(zone_);
27.128 + Local<Package> package(zone_, unit->module()->parent());
27.129 + if (!zone_->packages()->findOrAdd(package, import->path(), obj.address()))
27.130 + return false;
27.131 + if (!obj) {
27.132 + PathComponent *path = import->path();
27.133 + while (path->next)
27.134 + path = path->next;
27.135 + reportError(import->pos(), Message_CannotImportPath, path->name->chars());
27.136 + return false;
27.137 + }
27.138
27.139 -#if 0
27.140 - // For now we hardcode this...
27.141 - TranslationUnit *u2 = new (ZONE()->pool()) TranslationUnit();
27.142 - u2->path_ = "C:\\Users\\dvander\\jitcraft\\jitcraft-2\\src\\Debug\\wizard.sp";
27.143 + // If the object is a package, we will attempt to execute it
27.144 + // immediately after resolving imports.
27.145 + if (obj->isPackage()) {
27.146 + assert(false);
27.147 + } else {
27.148 + Local<Module> module(zone_, Module::cast(obj));
27.149 + if (!add(module))
27.150 + return false;
27.151 + }
27.152 + }
27.153
27.154 - ImportStatement *stmt = unit->tree()->imports()->at(0)->toImportStatement();
27.155 - stmt->setImportSource(u2);
27.156 + return true;
27.157 +}
27.158
27.159 - if (!u2->dependents_.append(unit))
27.160 +bool
27.161 +CompileContext::add(Handle<Module> module)
27.162 +{
27.163 + if (module->compiled())
27.164 + return true;
27.165 +
27.166 + TranslationUnit *tu = new (zone_->pool()) TranslationUnit(module);
27.167 +
27.168 + if (!unparsed_.append(tu) || !units_.append(tu))
27.169 return false;
27.170
27.171 - if (!addTranslationUnit(u2))
27.172 - return false;
27.173 -#endif
27.174 + return true;
27.175 }
27.176
27.177 bool
27.178 @@ -165,6 +221,7 @@
27.179 while (!unparsed_.empty()) {
27.180 TranslationUnit *unit = unparsed_.popCopy();
27.181
27.182 + AutoEnterCompileContext enter(*this, unit);
27.183 if (!parse(unit))
27.184 continue;
27.185
27.186 @@ -238,7 +295,7 @@
27.187 if (!unit->errors()->length())
27.188 continue;
27.189
27.190 - reporter->beginCompilationErrors(unit->path_);
27.191 + reporter->beginCompilationErrors(unit->module()->path()->chars());
27.192 for (size_t j = 0; j < unit->errors()->length(); j++) {
27.193 const CompileError &error = unit->errors()->at(j);
27.194 reporter->reportCompilationError(error.message, error.line, error.col);
27.195 @@ -285,7 +342,8 @@
27.196 va_end(ap);
27.197 }
27.198
27.199 -TranslationUnit::~TranslationUnit()
27.200 +void
27.201 +TranslationUnit::destroy()
27.202 {
27.203 for (size_t i = 0; i < errors_.length(); i++)
27.204 FreeErrorMessage(errors_[i].message);
28.1 --- a/src/compiler/CompileContext.h Sat Dec 29 00:55:38 2012 -0800
28.2 +++ b/src/compiler/CompileContext.h Tue Jan 01 15:34:07 2013 -0800
28.3 @@ -1,19 +1,19 @@
28.4 /*
28.5 * Copyright (C) 2012 David Anderson
28.6 *
28.7 - * This file is part of JITCraft.
28.8 + * This file is part of SourcePawn.
28.9 *
28.10 - * JITCraft is free software: you can redistribute it and/or modify it under
28.11 + * SourcePawn is free software: you can redistribute it and/or modify it under
28.12 * the terms of the GNU General Public License as published by the Free
28.13 * Software Foundation, either version 3 of the License, or (at your option)
28.14 * any later version.
28.15 *
28.16 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
28.17 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
28.18 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
28.19 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
28.20 *
28.21 * You should have received a copy of the GNU General Public License along with
28.22 - * JITCraft. If not, see http://www.gnu.org/licenses/.
28.23 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
28.24 */
28.25 #ifndef _include_jitcraft_compile_context_h_
28.26 #define _include_jitcraft_compile_context_h_
28.27 @@ -24,6 +24,7 @@
28.28 #include "../PoolAllocator.h"
28.29 #include "../Handles.h"
28.30 #include "../Modules.h"
28.31 +#include "../Packages.h"
28.32
28.33 namespace ke {
28.34
28.35 @@ -54,20 +55,21 @@
28.36 const char *message;
28.37 };
28.38
28.39 -struct TranslationUnit
28.40 +struct TranslationUnit : public PoolObject
28.41 {
28.42 - TranslationUnit()
28.43 + TranslationUnit(Handle<Module> module)
28.44 : tree_(NULL),
28.45 importScope_(NULL),
28.46 globalScope_(NULL),
28.47 + module_(module),
28.48 oom_(false),
28.49 dependencyFailed_(false)
28.50 {
28.51 }
28.52 - ~TranslationUnit();
28.53 +
28.54 + void destroy();
28.55
28.56 ParseTree *tree_;
28.57 - const char *path_;
28.58 PoolList<TranslationUnit *> dependents_;
28.59 ImportScope *importScope_;
28.60 GlobalScope *globalScope_;
28.61 @@ -98,6 +100,9 @@
28.62 GlobalScope *globalScope() const {
28.63 return globalScope_;
28.64 }
28.65 + Handle<Module> module() {
28.66 + return module_;
28.67 + }
28.68
28.69 void setDependencyFailed() {
28.70 dependencyFailed_ = true;
28.71 @@ -127,16 +132,17 @@
28.72 TranslationUnit *active_;
28.73
28.74 private:
28.75 - char *loadSource(const char *file, size_t *length);
28.76 + char *loadSource(Handle<Module> module, size_t *length);
28.77 bool parse(TranslationUnit *unit);
28.78 - void evaluateImports(TranslationUnit *unit);
28.79 + bool evaluateImports(TranslationUnit *unit);
28.80 bool propagateFailure();
28.81 + bool add(Handle<Module> module);
28.82
28.83 public:
28.84 CompileContext(Zone *zone, const char *file);
28.85 ~CompileContext();
28.86
28.87 - bool addTranslationUnit(TranslationUnit *unit);
28.88 + bool initialize(Handle<Package> package, const char *name);
28.89 bool compile();
28.90 void enter(TranslationUnit *unit);
28.91 void leave();
29.1 --- a/src/compiler/NameBinding.cpp Sat Dec 29 00:55:38 2012 -0800
29.2 +++ b/src/compiler/NameBinding.cpp Tue Jan 01 15:34:07 2013 -0800
29.3 @@ -746,6 +746,8 @@
29.4 // Import every name.
29.5 assert(false);
29.6 } else {
29.7 + assert(false);
29.8 +#if 0
29.9 GlobalScope *other = node->source()->globalScope();
29.10 Symbol *sym = other->findPublic(node->name());
29.11 if (!sym) {
29.12 @@ -753,6 +755,7 @@
29.13 return;
29.14 }
29.15 link_->scope()->addSymbol(sym);
29.16 +#endif
29.17 }
29.18 }
29.19
30.1 --- a/src/compiler/Parser.cpp Sat Dec 29 00:55:38 2012 -0800
30.2 +++ b/src/compiler/Parser.cpp Tue Jan 01 15:34:07 2013 -0800
30.3 @@ -221,11 +221,11 @@
30.4 bool
30.5 Parser::fullTypeAndName(Expression **type, String **namep, DeclKind kind)
30.6 {
30.7 - // Declaration:
30.8 - // NewDecl ::= Type Ident
30.9 - // OldDecl ::= Label? (Ident | "...")
30.10 - // Type ::= Ident
30.11 - // Label ::= Ident ":"
30.12 + // decl ::= newdecl | olddecl
30.13 + // newdecl ::= Type Ident
30.14 + // olddecl ::= Label? (Ident | "...")
30.15 + // type ::= Ident
30.16 + // label ::= Ident ":"
30.17 //
30.18 if (match(TOK_LABEL)) {
30.19 // We something of the form:
30.20 @@ -650,6 +650,7 @@
30.21 Statement *
30.22 Parser::while_()
30.23 {
30.24 + // while ::= "while" "(" expr ")" statement
30.25 SourcePosition pos = scanner_.begin();
30.26 scanner_.scan();
30.27
30.28 @@ -677,14 +678,11 @@
30.29 Statement *
30.30 Parser::do_()
30.31 {
30.32 + // do ::= "do" block "while" "(" expr ")"
30.33 SourcePosition pos = scanner_.begin();
30.34 scanner_.scan();
30.35
30.36 - Statement *body;
30.37 - if (scanner_.peek() == TOK_LBRACE)
30.38 - body = block();
30.39 - else
30.40 - body = localStatement();
30.41 + Statement *body = block();
30.42 if (!body)
30.43 return NULL;
30.44
30.45 @@ -705,6 +703,10 @@
30.46 Statement *
30.47 Parser::switch_()
30.48 {
30.49 + // switch ::= "switch" "(" expr ")" "{" case* defaultcase? "}"
30.50 + // case ::= "case" casevals ":" statement
30.51 + // defaultcase ::= "default" ":" statement
30.52 + //
30.53 expect(TOK_SWITCH);
30.54
30.55 SourcePosition pos = scanner_.begin();
30.56 @@ -796,6 +798,12 @@
30.57 Statement *
30.58 Parser::forStatement()
30.59 {
30.60 + // for ::= "for" "(" forinit? ";" forcond? ";" forstep ")" statement
30.61 + // forint ::= "new" vardecl |
30.62 + // exprstmt
30.63 + // forcond ::= expr
30.64 + // forstep ::= exprstmt
30.65 + //
30.66 SourcePosition pos = scanner_.begin();
30.67 scanner_.scan();
30.68 if (!expect(TOK_LPAREN))
30.69 @@ -844,6 +852,8 @@
30.70 ExpressionList *
30.71 Parser::dimensions()
30.72 {
30.73 + // dimensions ::= ("[" expr? "]")*
30.74 +
30.75 ExpressionList *postDimensions = new (pool_) ExpressionList();
30.76 while (match(TOK_LBRACKET)) {
30.77 Expression *dim = NULL;
30.78 @@ -863,9 +873,11 @@
30.79 VariableDeclaration *
30.80 Parser::var(TypeQualifiers qual)
30.81 {
30.82 + // vardecl ::= decl ("=" expr)?
30.83 +
30.84 Expression *type;
30.85 Local<String> name(zone_);
30.86 -
30.87 +
30.88 if (!typeAndName(&type, name.ref()))
30.89 return NULL;
30.90
30.91 @@ -900,6 +912,8 @@
30.92 Statement *
30.93 Parser::vars(TypeQualifiers qual)
30.94 {
30.95 + // localvars ::= ("new" | "const" | "decl") vardecl ("," vardecl)*
30.96 + // globalvars ::= ("public" | "const" | "new" | "public" "const") vardecl
30.97 VariableDeclaration *decl = var(qual);
30.98 if (!decl)
30.99 return NULL;
30.100 @@ -926,6 +940,9 @@
30.101 Statement *
30.102 Parser::returnStatement()
30.103 {
30.104 + // return ::= "return" term |
30.105 + // "return" "expr"
30.106 +
30.107 SourcePosition pos = scanner_.begin();
30.108 if (!expect(TOK_RETURN))
30.109 return NULL;
30.110 @@ -946,6 +963,7 @@
30.111 Statement *
30.112 Parser::expressionStatement()
30.113 {
30.114 + // exprstmt ::= expr
30.115 Expression *left = assignment();
30.116 if (!left)
30.117 return NULL;
30.118 @@ -956,6 +974,8 @@
30.119 Statement *
30.120 Parser::block()
30.121 {
30.122 + // block ::= "{" statement* "}"
30.123 +
30.124 if (!expect(TOK_LBRACE))
30.125 return NULL;
30.126
30.127 @@ -977,8 +997,11 @@
30.128 Statement *
30.129 Parser::if_()
30.130 {
30.131 + // if ::= "if" "(" expr ")" statement elseif* else?
30.132 + // elseif ::= "elseif" "(" expr ")" statement
30.133 + // else ::= "else" statement
30.134 expect(TOK_IF);
30.135 -
30.136 +
30.137 SourcePosition pos = scanner_.begin();
30.138 if (!expect(TOK_LPAREN))
30.139 return NULL;
30.140 @@ -1033,6 +1056,10 @@
30.141 Statement *
30.142 Parser::localStatement()
30.143 {
30.144 + // statement ::= stmt term
30.145 + // stmt ::= do | for | if | while | struct | enum |
30.146 + // localvars | return | switch | break | continue
30.147 +
30.148 Statement *statement = NULL;
30.149
30.150 // Statements which must be followed by a semicolon will break out of the
30.151 @@ -1115,6 +1142,10 @@
30.152 Statement *
30.153 Parser::struct_()
30.154 {
30.155 + // struct ::= "struct" name { struct_fields }
30.156 + // struct_fields ::= struct_field |
30.157 + // struct_field struct_fields
30.158 + // struct_field ::= label? name term
30.159 expect(TOK_STRUCT);
30.160
30.161 Local<String> name(zone_, expectName());
30.162 @@ -1160,6 +1191,10 @@
30.163 Statement *
30.164 Parser::enum_()
30.165 {
30.166 + // enum ::= "enum" name? { enum_members? }
30.167 + // enum_members ::= enum_member ","? |
30.168 + // enum_member "," enum_members
30.169 + // enum_member ::= ident ("=" constexpr)?
30.170 expect(TOK_ENUM);
30.171
30.172 SourcePosition pos = scanner_.begin();
30.173 @@ -1213,10 +1248,17 @@
30.174
30.175 SourcePosition pos = scanner_.begin();
30.176
30.177 + // import ::= import_path ("." "*")?
30.178 + // import_path ::= name |
30.179 + // name "." import_path
30.180 +
30.181 Local<String> name(zone_, expectName());
30.182 - if (!name || !names->append(NewScopedRoot<String>(pool_, name)))
30.183 + if (!name)
30.184 return NULL;
30.185
30.186 + PathComponent *root = new (pool_) PathComponent(NewScopedRoot<String>(pool_, name), NULL);
30.187 + PathComponent *current = root;
30.188 +
30.189 TokenKind suffix = TOK_NONE;
30.190 while (match(TOK_DOT)) {
30.191 if (match(TOK_STAR)) {
30.192 @@ -1227,11 +1269,11 @@
30.193 if ((name = expectName()) == NULL)
30.194 return NULL;
30.195
30.196 - if (!names->append(NewScopedRoot<String>(pool_, name)))
30.197 - return NULL;
30.198 + current->next = new (pool_) PathComponent(NewScopedRoot<String>(pool_, name), NULL);
30.199 + current = current->next;
30.200 }
30.201
30.202 - return new (pool_) ImportStatement(pos, names, suffix);
30.203 + return new (pool_) ImportStatement(pos, root, suffix);
30.204 }
30.205
30.206 Statement *
31.1 --- a/src/compiler/Scanner.cpp Sat Dec 29 00:55:38 2012 -0800
31.2 +++ b/src/compiler/Scanner.cpp Tue Jan 01 15:34:07 2013 -0800
31.3 @@ -197,7 +197,7 @@
31.4 return '\r';
31.5 case 't':
31.6 return '\t';
31.7 - case '\v':
31.8 + case 'v':
31.9 return '\v';
31.10
31.11 case 'x':
32.1 --- a/src/compiler/SemanticAnalysis.cpp Sat Dec 29 00:55:38 2012 -0800
32.2 +++ b/src/compiler/SemanticAnalysis.cpp Tue Jan 01 15:34:07 2013 -0800
32.3 @@ -64,7 +64,6 @@
32.4 unit_(unit),
32.5 hir_(NULL),
32.6 emitter_(pool_),
32.7 - module_(NULL),
32.8 loop_(NULL)
32.9 {
32.10 }
32.11 @@ -77,7 +76,6 @@
32.12 hir_(NULL),
32.13 scope_(parent->scope_),
32.14 emitter_(pool_),
32.15 - module_(parent->module_),
32.16 fun_(fun),
32.17 loop_(NULL),
32.18 control_(NULL)
32.19 @@ -90,8 +88,6 @@
32.20 {
32.21 scope_ = unit_->globalScope();
32.22
32.23 - module_ = Module::New(zone_);
32.24 -
32.25 for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
32.26 Statement *stmt = unit_->tree()->statements()->at(i);
32.27 stmt->accept(this);
32.28 @@ -100,19 +96,17 @@
32.29 Local<Struct> globals(zone_, unit_->globalScope()->build(zone_));
32.30 if (!globals)
32.31 return;
32.32 - module_->setGlobals(globals);
32.33 + unit_->module()->setGlobals(globals);
32.34
32.35 Local<Code> code(zone_, __ finish());
32.36 if (!code)
32.37 return;
32.38 - code->setModule(module_);
32.39 - module_->setCode(code);
32.40 + code->setModule(unit_->module());
32.41 + unit_->module()->setCode(code);
32.42
32.43 #ifndef NDEBUG
32.44 // Disassemble(code, stdout);
32.45 #endif
32.46 -
32.47 - unit_->module_ = module_;
32.48 }
32.49
32.50 void
32.51 @@ -187,7 +181,7 @@
32.52 Local<Code> code(zone_, __ finish());
32.53 if (!code)
32.54 return NULL;
32.55 - code->setModule(module_);
32.56 + code->setModule(unit_->module());
32.57
32.58 Local<Function> fun(zone_, Function::New(zone_, code, fun_, stmt->name(), stmt->pos()));
32.59 if (!fun)
32.60 @@ -909,7 +903,7 @@
32.61 }
32.62
32.63 // :TODO: remove
32.64 - assert(l == r);
32.65 + assert(*l == *r);
32.66
32.67 return left->type();
32.68 }
33.1 --- a/src/compiler/SemanticAnalysis.h Sat Dec 29 00:55:38 2012 -0800
33.2 +++ b/src/compiler/SemanticAnalysis.h Tue Jan 01 15:34:07 2013 -0800
33.3 @@ -248,7 +248,6 @@
33.4 HIR *hir_;
33.5 Scope *scope_;
33.6 BytecodeEmitter emitter_;
33.7 - ScopedRoot<Module> module_;
33.8 ScopedRoot<FunctionType> fun_;
33.9 LoopScope *loop_;
33.10 ControlScope *control_;
34.1 --- a/src/jitcraft.vcxproj Sat Dec 29 00:55:38 2012 -0800
34.2 +++ b/src/jitcraft.vcxproj Tue Jan 01 15:34:07 2013 -0800
34.3 @@ -23,16 +23,19 @@
34.4 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
34.5 <ConfigurationType>Application</ConfigurationType>
34.6 <UseDebugLibraries>true</UseDebugLibraries>
34.7 - <CharacterSet>Unicode</CharacterSet>
34.8 + <CharacterSet>MultiByte</CharacterSet>
34.9 + <PlatformToolset>v110</PlatformToolset>
34.10 </PropertyGroup>
34.11 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
34.12 <ConfigurationType>Application</ConfigurationType>
34.13 <UseDebugLibraries>false</UseDebugLibraries>
34.14 <WholeProgramOptimization>true</WholeProgramOptimization>
34.15 <CharacterSet>Unicode</CharacterSet>
34.16 + <PlatformToolset>v110</PlatformToolset>
34.17 </PropertyGroup>
34.18 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug - Library|Win32'">
34.19 <ConfigurationType>StaticLibrary</ConfigurationType>
34.20 + <PlatformToolset>v110</PlatformToolset>
34.21 </PropertyGroup>
34.22 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
34.23 <ImportGroup Label="ExtensionSettings">
34.24 @@ -60,7 +63,7 @@
34.25 </PrecompiledHeader>
34.26 <WarningLevel>Level3</WarningLevel>
34.27 <Optimization>Disabled</Optimization>
34.28 - <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions); _CRT_SECURE_NO_WARNINGS;KE_EXPORTING</PreprocessorDefinitions>
34.29 + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions); _CRT_SECURE_NO_WARNINGS;KE_EXPORTING;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE</PreprocessorDefinitions>
34.30 </ClCompile>
34.31 <Link>
34.32 <SubSystem>Console</SubSystem>
34.33 @@ -109,6 +112,7 @@
34.34 <ClCompile Include="compiler\Symbols.cpp" />
34.35 <ClCompile Include="Environments.cpp" />
34.36 <ClCompile Include="Exception.cpp" />
34.37 + <ClCompile Include="FileSystem.cpp" />
34.38 <ClCompile Include="FixedArray.cpp" />
34.39 <ClCompile Include="Functions.cpp" />
34.40 <ClCompile Include="GlobalRoots.cpp" />
34.41 @@ -118,6 +122,7 @@
34.42 <ClCompile Include="Modules.cpp" />
34.43 <ClCompile Include="NativeTable.cpp" />
34.44 <ClCompile Include="Opcodes.cpp" />
34.45 + <ClCompile Include="Packages.cpp" />
34.46 <ClCompile Include="Platform-Windows.cpp" />
34.47 <ClCompile Include="PoolAllocator.cpp" />
34.48 <ClCompile Include="Reference.cpp" />
34.49 @@ -152,6 +157,7 @@
34.50 <ClInclude Include="compiler\Symbols.h" />
34.51 <ClInclude Include="compiler\Token.h" />
34.52 <ClInclude Include="Environments.h" />
34.53 + <ClInclude Include="FileSystem.h" />
34.54 <ClInclude Include="FixedArray.h" />
34.55 <ClInclude Include="Functions.h" />
34.56 <ClInclude Include="GlobalRoots.h" />
34.57 @@ -160,6 +166,7 @@
34.58 <ClInclude Include="Heap-inl.h" />
34.59 <ClInclude Include="InlineList.h" />
34.60 <ClInclude Include="Interpreter.h" />
34.61 + <ClInclude Include="List.h" />
34.62 <ClInclude Include="Messages.h" />
34.63 <ClInclude Include="Modules.h" />
34.64 <ClInclude Include="Heap.h" />
34.65 @@ -167,6 +174,7 @@
34.66 <ClInclude Include="Objects.h" />
34.67 <ClInclude Include="ObjectVisitor.h" />
34.68 <ClInclude Include="Opcodes.h" />
34.69 + <ClInclude Include="Packages.h" />
34.70 <ClInclude Include="Platform.h" />
34.71 <ClInclude Include="PoolAllocator.h" />
34.72 <ClInclude Include="Handles.h" />
35.1 --- a/src/jitcraft.vcxproj.filters Sat Dec 29 00:55:38 2012 -0800
35.2 +++ b/src/jitcraft.vcxproj.filters Tue Jan 01 15:34:07 2013 -0800
35.3 @@ -109,6 +109,12 @@
35.4 <ClCompile Include="compiler\ConstantEvaluator.cpp">
35.5 <Filter>Source Files\compiler</Filter>
35.6 </ClCompile>
35.7 + <ClCompile Include="Packages.cpp">
35.8 + <Filter>Source Files</Filter>
35.9 + </ClCompile>
35.10 + <ClCompile Include="FileSystem.cpp">
35.11 + <Filter>Source Files</Filter>
35.12 + </ClCompile>
35.13 </ItemGroup>
35.14 <ItemGroup>
35.15 <ClInclude Include="Handles-inl.h">
35.16 @@ -273,6 +279,15 @@
35.17 <ClInclude Include="VirtualObjectVisitor.h">
35.18 <Filter>Header Files\vm</Filter>
35.19 </ClInclude>
35.20 + <ClInclude Include="Packages.h">
35.21 + <Filter>Header Files\vm</Filter>
35.22 + </ClInclude>
35.23 + <ClInclude Include="FileSystem.h">
35.24 + <Filter>Header Files\vm</Filter>
35.25 + </ClInclude>
35.26 + <ClInclude Include="List.h">
35.27 + <Filter>Header Files\vm</Filter>
35.28 + </ClInclude>
35.29 </ItemGroup>
35.30 <ItemGroup>
35.31 <None Include="Messages.tbl">
36.1 --- a/src/main.cpp Sat Dec 29 00:55:38 2012 -0800
36.2 +++ b/src/main.cpp Tue Jan 01 15:34:07 2013 -0800
36.3 @@ -20,6 +20,14 @@
36.4 #include <stdlib.h>
36.5 #include <string.h>
36.6 #include "../include/keima.h"
36.7 +#include "Utility.h"
36.8 +#include "Platform.h"
36.9 +#ifdef WIN32
36.10 +# include <Windows.h>
36.11 +# include <direct.h>
36.12 +#else
36.13 +# include <unistd.h>
36.14 +#endif
36.15
36.16 using namespace Ke;
36.17
36.18 @@ -34,11 +42,22 @@
36.19
36.20 IStackFrameIterator *iter = Keima::NewStackFrameIterator();
36.21 unsigned index = 0;
36.22 +
36.23 + const char *filename = iter->source();
36.24 + if (!filename)
36.25 + filename = "<anonymous>";
36.26 + if (const char *tail = strrchr(filename, '/'))
36.27 + filename = tail + 1;
36.28 +#ifdef WIN32
36.29 + if (const char *tail = strrchr(filename, '\\'))
36.30 + filename = tail + 1;
36.31 +#endif
36.32 +
36.33 while (!iter->done() && index < 10) {
36.34 fprintf(stderr, "[%d] %s (%s line %d)\n",
36.35 index,
36.36 iter->function(),
36.37 - iter->source(),
36.38 + filename,
36.39 iter->lineNumber());
36.40 iter->prev();
36.41 index++;
36.42 @@ -107,6 +126,14 @@
36.43 if (!Keima::Initialize())
36.44 return 1;
36.45
36.46 + ke::AutoFree<char> fullpath;
36.47 + if (!ke::OS::GetAbsolutePath(argv[1], fullpath))
36.48 + return 1;
36.49 +
36.50 + ke::AutoFree<char> path, name;
36.51 + if (!ke::OS::SplitPath(*fullpath, path, name))
36.52 + return 1;
36.53 +
36.54 int rval = 0;
36.55
36.56 Keima::InstallMessageReporter(&s_Reporter);
36.57 @@ -115,7 +142,13 @@
36.58 Keima::SetPublicFunctionListener(&entry);
36.59
36.60 HandleScope scope;
36.61 - if (!Compile(argv[1])) {
36.62 + Local<Package> package = Package::New(Handle<Package>(), Handle<String>(), *path, Package::Normal);
36.63 + if (!package) {
36.64 + rval = 1;
36.65 + break;
36.66 + }
36.67 +
36.68 + if (!Keima::Compile(package, *name)) {
36.69 rval = 1;
36.70 break;
36.71 }
37.1 --- a/tests/basic/divide-by-zero.err Sat Dec 29 00:55:38 2012 -0800
37.2 +++ b/tests/basic/divide-by-zero.err Tue Jan 01 15:34:07 2013 -0800
37.3 @@ -1,3 +1,3 @@
37.4 Uncaught exception: integer divide by zero
37.5 -[0] f ((anonymous) line 1)
37.6 -[1] main ((anonymous) line 3)
37.7 +[0] f (divide-by-zero.sp line 1)
37.8 +[1] main (divide-by-zero.sp line 3)
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/tests/basic/import-sysroot-all.sp Tue Jan 01 15:34:07 2013 -0800
38.3 @@ -0,0 +1,9 @@
38.4 +import shell.*;
38.5 +
38.6 +public main()
38.7 +{
38.8 + PrintNum(5);
38.9 + PrintString(" is ");
38.10 + PrintFloat(5.0);
38.11 +}
38.12 +
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/tests/basic/import-sysroot-select.sp Tue Jan 01 15:34:07 2013 -0800
39.3 @@ -0,0 +1,11 @@
39.4 +import shell;
39.5 +import shell;
39.6 +import shell;
39.7 +
39.8 +public main()
39.9 +{
39.10 + shell.PrintNum(5);
39.11 + shell.PrintString(" is ");
39.12 + shell.PrintFloat(5.0);
39.13 +}
39.14 +
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/tests/shell.sp Tue Jan 01 15:34:07 2013 -0800
40.3 @@ -0,0 +1,5 @@
40.4 +native PrintNum(num);
40.5 +
40.6 +native PrintString(const char:text[]);
40.7 +
40.8 +native PrintFloat(float:f);