diff -r 5acf0c693bae Crack.cc--- a/Crack.cc Mon Dec 13 11:33:44 2010 -0500+++ b/Crack.cc Wed Dec 22 10:05:35 2010 -0500@@ -66,7 +66,11 @@ // and we get dependency issues new GlobalNamespace(0, ".builtin"), new GlobalNamespace(0, ".builtin"));+ builtinContext->compileTime = true; builtinMod = rootBuilder->registerPrimFuncs(*builtinContext);+ //rootBuilder->bindCompiletimeModule(builtinMod);+ rootBuilder->bindRuntimeModule(builtinMod);+ moduleCache[".builtin"] = builtinMod; // alias builtins to the root namespace for (Namespace::VarDefMap::iterator i = builtinContext->ns->beginDefs();@@ -196,11 +200,19 @@ Parser parser(toker, &context); parser.parse(); module->close(context);+ // initial binding+ if (module->annotations)+ context.builder.bindCompiletimeModule(module);+ else+ context.builder.bindRuntimeModule(module);+ } ModuleDefPtr Crack::initExtensionModule(const string &canonicalName, Crack::InitFunc initFunc ) {++cerr << "start initExtensionModule [" << canonicalName << "]\n"; // create a new context BuilderPtr builder = rootBuilder->createChildBuilder(); ContextPtr context =@@ -214,11 +226,19 @@ ModuleDefPtr modDef = context->createModule(canonicalName); Module mod(context.get()); initFunc(&mod);- if (mod.hasAnnotations())+ modDef->fromExtension = true;+ if (mod.hasAnnotations()) { modDef->annotations = true;+ context->compileTime = true;+ } mod.finish(); modDef->close(*context);- ++ if (mod.hasAnnotations())+ builder->bindCompiletimeModule(modDef);++cerr << "end initExtensionModule [" << canonicalName << "]\n";+ return modDef; }@@ -262,6 +282,7 @@ string &canonicalName, bool annotations ) {+ // create the dotted canonical name of the module for (StringVecIter iter = moduleNameBegin; iter != moduleNameEnd;@@ -271,11 +292,20 @@ canonicalName += "." + *iter; else canonicalName = *iter;-+cerr << "&&&&& start loadModule: " << canonicalName << ", annotations: " << annotations << "\n"; // check to see if we have it in the cache ModuleMap::iterator iter = moduleCache.find(canonicalName);- if (iter != moduleCache.end())+ if (iter != moduleCache.end()) {+ // ensure this module has been bound in the right runtime/compiletime+ // context. we run this each time, but the bind functions only ever+ // bind once, respectively+ if (annotations)+ rootBuilder->bindCompiletimeModule(iter->second);+ else+ rootBuilder->bindRuntimeModule(iter->second);+cerr << "&&&&& end loadModule: " << canonicalName << ", annotations: " << annotations << "\n"; return iter->second;+ } // load the parent module StringVec::const_reverse_iterator rend(moduleNameEnd);@@ -325,8 +355,10 @@ ) ); context->toplevel = true;+ context->compileTime = annotations; modDef = context->createModule(canonicalName); modDef->annotations = annotations;+ modDef->isDirectory = modPath.isDir; moduleCache[canonicalName] = modDef; if (!modPath.isDir) { ifstream src(modPath.path.c_str());@@ -336,6 +368,7 @@ modDef->finished = true; loadedModules.push_back(modDef);+cerr << "&&&&& end loadModule: " << canonicalName << ", annotations: " << annotations << "\n"; return modDef; } @@ -382,7 +415,8 @@ // delegates to the original root context - this is the "bootstrapped // context." It contains all of the special definitions that were // extracted from the bootstrapping modules.- rootContext = rootContext->createSubContext(Context::module);+ rootContext = rootContext->createSubContext(Context::module,+ rootContext->compileTime); // extract some constants VarDefPtr v = mod->lookUp("true");diff -r 5acf0c693bae builder/Builder.h--- a/builder/Builder.h Mon Dec 13 11:33:44 2010 -0500+++ b/builder/Builder.h Wed Dec 22 10:05:35 2010 -0500@@ -401,6 +401,16 @@ virtual void initializeImport(model::ModuleDefPtr) = 0; /**+ * Bind a module in a runtime context+ */+ virtual void bindRuntimeModule(model::ModuleDefPtr) = 0;++ /**+ * Bind a module in a compiletime context (annotation)+ */+ virtual void bindCompiletimeModule(model::ModuleDefPtr) = 0;++ /** * Provides the builder with access to the program's argument list. */ virtual void setArgv(int argc, char **argv) = 0;diff -r 5acf0c693bae builder/llvm/BFuncDef.cc--- a/builder/llvm/BFuncDef.cc Mon Dec 13 11:33:44 2010 -0500+++ b/builder/llvm/BFuncDef.cc Wed Dec 22 10:05:35 2010 -0500@@ -7,14 +7,20 @@ #include <llvm/Function.h>+// XXX debug only+#include <iostream>+ using namespace builder::mvll; void BFuncDef::setOwner(model::Namespace *o) { owner = o; fullName.clear(); // if an overridden symbolName isn't set, we use the canonical name- if (symbolName.empty())+ if (symbolName.empty()) {+ definitionRep->setName(getFullName());+ std::cerr << "changing symbol from [" << rep->getNameStr() << "] to [" << getFullName() << "]\n"; rep->setName(getFullName());+ } } llvm::Function * BFuncDef::getRep(LLVMBuilder &builder, bool needMapping) {diff -r 5acf0c693bae builder/llvm/BFuncDef.h--- a/builder/llvm/BFuncDef.h Mon Dec 13 11:33:44 2010 -0500+++ b/builder/llvm/BFuncDef.h Wed Dec 22 10:05:35 2010 -0500@@ -19,10 +19,15 @@ class BFuncDef : public model::FuncDef { public:- // this holds the function object for the last module to request+ // this holds the declaration function object for the last module to request // it. llvm::Function *rep;+ // this holds the function object for the original Function definition+ // (as opposed to declarations created in other modules)+ // we need this for compileTime jitting+ llvm::Function *definitionRep;+ // low level symbol name as used by llvm::Function *rep // this should be empty, unless it needs to link against an external symbol // when it's empty, rep->name will default to the crack canonical name,@@ -44,6 +49,7 @@ ) : model::FuncDef(flags, name, argCount), rep(0),+ definitionRep(0), symbolName(), vtableSlot(0) { }diff -r 5acf0c693bae builder/llvm/BModuleDef.h--- a/builder/llvm/BModuleDef.h Mon Dec 13 11:33:44 2010 -0500+++ b/builder/llvm/BModuleDef.h Wed Dec 22 10:05:35 2010 -0500@@ -11,6 +11,10 @@ class Context; }+namespace llvm {+ class Module;+}+ namespace builder { namespace mvll {@@ -19,11 +23,25 @@ class BModuleDef : public model::ModuleDef { public:++ // we may store up to two separate instances of the Module*, since+ // a module may be used in runtime context, compiletime context (annotation)+ // or both. we only want to parse a module once, so once one of these+ // is set, if the other is needed it will be cloned.++ // runtime-time Module, i.e. the one used in the Linker+ llvm::Module *rtModule;++ // compile-time Module, i.e. the one used in the JIT for annotations+ llvm::Module *ctModule;+ // primitive cleanup function void (*cleanup)(); BModuleDef(const std::string &canonicalName, model::Namespace *parent) : ModuleDef(canonicalName, parent),+ rtModule(0),+ ctModule(0), cleanup(0) { }diff -r 5acf0c693bae builder/llvm/FuncBuilder.cc--- a/builder/llvm/FuncBuilder.cc Mon Dec 13 11:33:44 2010 -0500+++ b/builder/llvm/FuncBuilder.cc Wed Dec 22 10:05:35 2010 -0500@@ -8,6 +8,9 @@ #include <llvm/LLVMContext.h>+// XXX debug only+#include <llvm/Module.h>+ using namespace llvm; using namespace model; using namespace std;@@ -62,7 +65,7 @@ func->setCallingConv(llvm::CallingConv::C); if (!funcDef->symbolName.empty()) func->setName(funcDef->symbolName);-+cerr << "created function definition [" << func->getNameStr() << "] in parent [" << builder.module->getModuleIdentifier() << "] at llvm Function* " << func << ", model Function *" << funcDef.get() << "\n"; // back-fill builder data and set arg names Function::arg_iterator llvmArg = func->arg_begin(); vector<ArgDefPtr>::const_iterator crackArg =@@ -104,6 +107,8 @@ funcDef->impl = new BConstDefImpl(func); funcDef->rep = func;+ funcDef->definitionRep = func;+ if (storeDef) context.ns->addDef(funcDef.get()); }diff -r 5acf0c693bae builder/llvm/LLVMBuilder.cc--- a/builder/llvm/LLVMBuilder.cc Mon Dec 13 11:33:44 2010 -0500+++ b/builder/llvm/LLVMBuilder.cc Wed Dec 22 10:05:35 2010 -0500@@ -44,6 +44,7 @@ #include <llvm/ExecutionEngine/JIT.h> // link in the JIT #include <llvm/Linker.h> #include <llvm/Support/StandardPasses.h>+#include <llvm/Transforms/Utils/Cloning.h> #include <spug/Exception.h> #include <spug/StringFmt.h>@@ -200,13 +201,15 @@ // create the class context ContextPtr classCtx =- context.createSubContext(Context::instance, classType);+ context.createSubContext(Context::instance, context.compileTime,+ classType); CompositeNamespacePtr ns = new CompositeNamespace(classType, context.ns.get() ); ContextPtr lexicalContext = - classCtx->createSubContext(Context::composite, ns.get());+ classCtx->createSubContext(Context::composite,+ context.compileTime, ns.get()); BBuilderContextData *bdata; lexicalContext->builderData = bdata = new BBuilderContextData();@@ -326,7 +329,7 @@ // only link once if (linkedModules.find(mod) == linkedModules.end()) {-+cerr << "--linking: " << mod->getModuleIdentifier() << "\n"; string errMsg; getLinker()->LinkInModule(mod, &errMsg); linkedModules[mod] = true;@@ -393,19 +396,20 @@ /** * ensures we have a Function* declaration for this specific Module*- * sinc llvm requires separate decls during link.+ * since llvm requires separate decls during link. * needMapping is required only for annotation functions */ Function *LLVMBuilder::getModFunc(FuncDef *funcDef, bool needMapping) {+ ModFuncMap::iterator iter = moduleFuncs.find(funcDef); if (iter == moduleFuncs.end()) {-+cerr << "in [" << module->getModuleIdentifier() << "] getModFunc on " << funcDef->getFullName() << ", needMapping: " << needMapping << "\n"; // not found, create a new one and map it to the existing function // pointer BFuncDef *bfuncDef = BFuncDefPtr::acast(funcDef); Function *func(0);- if (bfuncDef->rep->getNameStr() == "abort") {+ if (bfuncDef->definitionRep->getNameStr() == "abort") { // special case for abort: since we may already have a definition // for abort() from emitAbort(), we can't blindly make it here, // we have to reuse it if it exists@@ -413,21 +417,22 @@ } if (!func)- func = Function::Create(bfuncDef->rep->getFunctionType(),+ func = Function::Create(bfuncDef->definitionRep->getFunctionType(), Function::ExternalLinkage,- bfuncDef->rep->getNameStr(),+ bfuncDef->definitionRep->getNameStr(), module ); // low level symbol name if (!bfuncDef->symbolName.empty()) func->setName(bfuncDef->symbolName);-- // add a mapping if requested- // this is needed for annotations. if it's not an annotation, the JIT- // won't have a copy of it since it wasn't added during createModule+cerr << "created declare to function [" << func->getNameStr() << "] at Function *" << func << " in [" << module->getModuleIdentifier() << "] from llvm Function* " << bfuncDef->definitionRep << ", model Function *" << funcDef << "\n";+ // add a mapping if requested. for use by compileTime functions+ // i.e. annotations if (needMapping) {- void *fp = getJIT()->getPointerToFunction(bfuncDef->rep);+ cerr << "**looking for: " << bfuncDef->definitionRep->getNameStr() << " from its definition in module: " << bfuncDef->definitionRep->getParent()->getModuleIdentifier() << "\n";+ void *fp = getJIT()->getPointerToFunction(bfuncDef->definitionRep);+ cerr << "**got: " << bfuncDef->definitionRep->getNameStr() << "\n"; if (fp) getJIT()->addGlobalMapping(func, fp); }@@ -607,8 +612,10 @@ // exactly one module should contain a definition, all others should be // just a declaration. getRep calls getModFunc which ensures we have // the correct Function* for this builder's Module*+cerr << "emitFuncCall [" << funcDef->getFullName() << "], compileTime: " << context.compileTime << "\n"; lastValue =- builder.CreateCall(funcDef->getRep(*this), valueArgs.begin(),+ builder.CreateCall(funcDef->getRep(*this, context.compileTime),+ valueArgs.begin(), valueArgs.end() ); /*@@ -1145,8 +1152,9 @@ } ContextPtr funcCtx = - context.createSubContext(Context::local, new - LocalNamespace(context.ns.get(), name)+ context.createSubContext(Context::local,+ context.compileTime,+ new LocalNamespace(context.ns.get(), name) ); FuncBuilder f(*funcCtx, flags,@@ -1345,7 +1353,7 @@ // construct the vtable if necessary if (type->hasVTable) { VTableBuilder vtableBuilder(- this,+ context, BTypeDefPtr::arcast(context.globalData->vtableBaseType), module );@@ -1671,6 +1679,116 @@ return newModule; }+void LLVMBuilder::bindCompiletimeModule(ModuleDefPtr m) {++ if (m->isDirectory)+ return;++cerr << " bindCompiletime: " << m->getFullName() << "\n";+ BModuleDef *crackMod = BModuleDefPtr::rcast<ModuleDef>(m);++ if (crackMod->ctModule) {+ // already bound+ cerr << " already bound\n";+ return;+ }++ if (m->fromExtension) {+cerr << "--jittin from extension " << m->getFullName() << "\n";+ for (map<Function *, void *>::iterator iter = primFuncs.begin();+ iter != primFuncs.end();+ ++iter) {+ cerr << "binding prim func [" << iter->first->getNameStr() << "]\n";+ getJIT()->addGlobalMapping(iter->first, iter->second);+ }+ // flag this so we don't bind again+ crackMod->ctModule = (Module*)1;+ return;+ }+++ // if rtModule is bound, then this module has alrady been bound+ // in the compile-time context, so we clone that module+ if (crackMod->rtModule) {+ crackMod->ctModule = CloneModule(crackMod->rtModule);+ crackMod->ctModule->setModuleIdentifier(+ crackMod->ctModule->getModuleIdentifier()+":rtclone");++ // only in this direction (cloning runTime for compileTime) do we have+ // to update all model::FuncDef objects in this model::ModulDef so that+ // the definitionRep points to the cloned version. otherwise, the+ // addGlobalMapping calls in getModFunc will point to the wrong+ // llvm::Function* + /*+ for (Module::const_iterator I = crackMod->rtModule->begin(),+ E = crackMod->rtModule->end();+ I != E;+ ++I) {+ if (!I->isDeclaration()) {+ cerr << "XXX DOES THIS WORK: " << I->getNameStr() << "\n";+ //bm->definitionRep = NULL; // set to null, look up lazily in getModFunc from rtModule+ //crackMod->ctModule->getFunction(I->getName());+ //cerr << "XXX YES IT SET TO: " << bm->definitionRep->getNameStr() << "\n";++ }+ */++ cerr << " cloned rtModule\n";+ }+ else {+ // a first binding. bind to this builder's module, since we just+ // generated it, it's the original+ crackMod->ctModule = module;+ cerr << " used builder module [" << module->getModuleIdentifier() << "]\n";+ }++ // we should probably pull out functions we know are annotations+ // and JIT them explicitly, rather than the whole module+ // perhaps just making the JIT lazy is enough, since getFuncAddr()+ // should only be called on annotation functions+cerr << "--jittin: " << crackMod->ctModule->getModuleIdentifier() << "\n";+ getJIT()->addModule(crackMod->ctModule);+++}++void LLVMBuilder::bindRuntimeModule(ModuleDefPtr m) {++ if (m->fromExtension || m->isDirectory)+ return;++cerr << " bindRuntime: " << m->getFullName() << "\n";+ BModuleDef *crackMod = BModuleDefPtr::rcast<ModuleDef>(m);++ if (crackMod->rtModule) {+ // already bound+ cerr << " already bound\n";+ return;+ }++bindCompiletimeModule(m);++ // if ctModule is bound, then this module has alrady been bound+ // in the run-time context, so we clone that module+ if (crackMod->ctModule) {+ crackMod->rtModule = CloneModule(crackMod->ctModule);+ crackMod->rtModule->setModuleIdentifier(crackMod->rtModule->getModuleIdentifier()+":ctclone");+ // since the model::FuncDefs in this model::ModuleDef were already jitted,+ // there's nothing else special to do here (see bindCompileTime for the+ // difference in that direction)+ cerr << " cloned ctModule\n";+ }+ else {+ // a first binding. bind to this builder's module, since we just+ // generated it, it's the original+ crackMod->rtModule = module;+ cerr << " used builder module [" << module->getModuleIdentifier() << "]\n";+ }++ linkModule(crackMod->rtModule);++}+ void LLVMBuilder::closeModule(Context &context, ModuleDef *moduleDef) { assert(module);@@ -1689,24 +1807,6 @@ closeAllCleanupsStatic(context); builder.CreateRetVoid();- // bind the module to the execution engine if this module contains- // annotations. otherwise, just link it- if (moduleDef->annotations) {- // we should probably pull out functions we know are annotations- // and JIT them explicitly, rather than the whole module- // perhaps just making the JIT lazy is enough, since getFuncAddr()- // should only be called on annotation functions- getJIT()->addModule(module);- for (map<Function *, void *>::iterator iter = primFuncs.begin();- iter != primFuncs.end();- ++iter- )- getJIT()->addGlobalMapping(iter->first, iter->second);- }- else {- linkModule(module);- }- if (debugInfo) delete debugInfo;@@ -2228,7 +2328,7 @@ createOperClassFunc(context, vtableBaseType, metaType.get()); // build VTableBase's vtable- VTableBuilder vtableBuilder(this, vtableBaseType, module);+ VTableBuilder vtableBuilder(context, vtableBaseType, module); vtableBaseType->createAllVTables(vtableBuilder, ".vtable.VTableBase", vtableBaseType );@@ -2244,10 +2344,6 @@ // byteptr array indexing addArrayMethods(context, byteptrType, byteType); - // link the builtin module. as this is the first module built, it should- // create the linker instance- linkModule(module);- return bMod; }@@ -2288,8 +2384,9 @@ void LLVMBuilder::initializeImport(model::ModuleDefPtr m) {- // if the module has annotations, there is no top level to run- if (m->annotations)+ // if the module has annotations or is from an extension,+ // there is no top level to run+ if (m->annotations || m->fromExtension) return; // we add a call into our module's :main function@@ -2404,7 +2501,20 @@ } // otherwise, JIT the final linked IR- getJIT()->addModule(finalir);+ InitializeNativeTarget();+ string errMsg;+ ExecutionEngine *eng =+ ExecutionEngine::createJIT(finalir,+ &errMsg, // error string+ 0, // JIT memory manager+ CodeGenOpt::None, // opt lvl+ false // alloc globals with code+ );++ if (!eng) {+ cerr << errMsg << endl;+ return;+ } Function *main = finalir->getFunction(options->mainUnit+":main"); if (!main) {@@ -2412,8 +2522,8 @@ return; }- int (*fptr)() = (int (*)())getJIT()->getPointerToFunction(main);- void (*cptr)() = (void (*)())getJIT()->getPointerToFunction(finalCleanup);+ int (*fptr)() = (int (*)())eng->getPointerToFunction(main);+ void (*cptr)() = (void (*)())eng->getPointerToFunction(finalCleanup); // JIT main entry point fptr();diff -r 5acf0c693bae builder/llvm/LLVMBuilder.h--- a/builder/llvm/LLVMBuilder.h Mon Dec 13 11:33:44 2010 -0500+++ b/builder/llvm/LLVMBuilder.h Wed Dec 22 10:05:35 2010 -0500@@ -336,6 +336,10 @@ virtual void initializeImport(model::ModuleDefPtr);+ virtual void bindRuntimeModule(model::ModuleDefPtr);++ virtual void bindCompiletimeModule(model::ModuleDefPtr);+ virtual void setArgv(int argc, char **argv); virtual void run();diff -r 5acf0c693bae builder/llvm/VTableBuilder.cc--- a/builder/llvm/VTableBuilder.cc Mon Dec 13 11:33:44 2010 -0500+++ b/builder/llvm/VTableBuilder.cc Wed Dec 22 10:05:35 2010 -0500@@ -61,7 +61,9 @@ // insert the function vector<Constant *> &entries = targetVTable->entries; accomodate(entries, func->vtableSlot);- entries[func->vtableSlot] = (Constant*)func->getRep(*builder);+ LLVMBuilder &b = dynamic_cast<LLVMBuilder &>(context.builder);+ entries[func->vtableSlot] = (Constant*)func->getRep(b,+ context.compileTime); } // add the function to all vtables.@@ -72,7 +74,9 @@ ) { vector<Constant *> &entries = iter->second->entries; accomodate(entries, func->vtableSlot);- entries[func->vtableSlot] = (Constant*)func->getRep(*builder);+ LLVMBuilder &b = dynamic_cast<LLVMBuilder &>(context.builder);+ entries[func->vtableSlot] = (Constant*)func->getRep(b,+ context.compileTime); } }diff -r 5acf0c693bae builder/llvm/VTableBuilder.h--- a/builder/llvm/VTableBuilder.h Mon Dec 13 11:33:44 2010 -0500+++ b/builder/llvm/VTableBuilder.h Wed Dec 22 10:05:35 2010 -0500@@ -15,12 +15,15 @@ class Module; }+namespace model {+ class Context;+}+ namespace builder { namespace mvll { class BTypeDef; class BFuncDef;-class LLVMBuilder; SPUG_RCPTR(VTableInfo);@@ -58,16 +61,16 @@ llvm::Module *module; // used to get correct Function* for the builder's Module*- LLVMBuilder *builder;+ model::Context &context; public:- VTableBuilder(LLVMBuilder *b,+ VTableBuilder(model::Context &c, BTypeDef *vtableBaseType, llvm::Module *m) : firstVTable(0), vtableBaseType(vtableBaseType), module(m),- builder(b) {+ context(c) { } void dump();diff -r 5acf0c693bae ext/Func.cc--- a/ext/Func.cc Mon Dec 13 11:33:44 2010 -0500+++ b/ext/Func.cc Wed Dec 22 10:05:35 2010 -0500@@ -76,7 +76,8 @@ if (flags & constructor) { TypeDefPtr myClass = TypeDefPtr::arcast(context->ns);- ContextPtr funcContext = context->createSubContext(Context::local);+ ContextPtr funcContext = context->createSubContext(Context::local,+ context->compileTime); // create the "this" variable ArgDefPtr thisDef =diff -r 5acf0c693bae model/Context.cc--- a/model/Context.cc Mon Dec 13 11:33:44 2010 -0500+++ b/model/Context.cc Wed Dec 22 10:05:35 2010 -0500@@ -64,6 +64,7 @@ toplevel(false), emittingCleanups(false), terminal(false),+ compileTime(false), returnType(parentContext ? parentContext->returnType : TypeDefPtr(0)), nextFuncFlags(FuncDef::noFlags), globalData(parentContext ? parentContext->globalData : new GlobalData()),@@ -82,6 +83,7 @@ toplevel(false), emittingCleanups(false), terminal(false),+ compileTime(false), returnType(TypeDefPtr(0)), nextFuncFlags(FuncDef::noFlags), globalData(globalData),@@ -90,7 +92,10 @@ Context::~Context() {}-ContextPtr Context::createSubContext(Scope newScope, Namespace *ns) {+ContextPtr Context::createSubContext(Scope newScope,+ bool compileTime0,+ Namespace *ns) {+ if (!ns) { switch (newScope) { case local:@@ -107,7 +112,10 @@ ); } }- return new Context(builder, newScope, this, ns, compileNS.get());+ Context *c = new Context(builder, newScope, this, ns, compileNS.get());+ c->compileTime = compileTime0;+cerr << "new subcontext, compileTime: " << compileTime << "\n";+ return c; } ContextPtr Context::getClassContext() {diff -r 5acf0c693bae model/Context.h--- a/model/Context.h Mon Dec 13 11:33:44 2010 -0500+++ b/model/Context.h Wed Dec 22 10:05:35 2010 -0500@@ -96,6 +96,9 @@ // if true, a terminal statement has been emitted in the context. bool terminal;+ // if true, we're in a compile-time context (i.e. annotation)+ bool compileTime;+ // this is the return type for a function context, and the class type // for a class context. TypeDefPtr returnType;@@ -160,13 +163,16 @@ * Create a new subcontext with a different scope from the parent * context. */- ContextPtr createSubContext(Scope newScope, Namespace *ns = 0);+ ContextPtr createSubContext(Scope newScope,+ bool compileTime0,+ Namespace *ns = 0+ ); /** * Create a new subcontext in the same scope. */ ContextPtr createSubContext() {- return createSubContext(scope, 0);+ return createSubContext(scope, compileTime, 0); } /**diff -r 5acf0c693bae model/ModuleDef.cc--- a/model/ModuleDef.cc Mon Dec 13 11:33:44 2010 -0500+++ b/model/ModuleDef.cc Wed Dec 22 10:05:35 2010 -0500@@ -12,6 +12,8 @@ Namespace(name), parent(parent), annotations(false),+ fromExtension(false),+ isDirectory(false), finished(false) { }diff -r 5acf0c693bae model/ModuleDef.h--- a/model/ModuleDef.h Mon Dec 13 11:33:44 2010 -0500+++ b/model/ModuleDef.h Wed Dec 22 10:05:35 2010 -0500@@ -31,6 +31,13 @@ // close() method has been called. bool finished;+ // this is true if the module was loaded from an extension+ // it indicates that (at least) there is no top level code to run+ bool fromExtension;++ // true if this module was loaded from a directory+ bool isDirectory;+ ModuleDef(const std::string &name, Namespace *parent); /**diff -r 5acf0c693bae model/TypeDef.cc--- a/model/TypeDef.cc Mon Dec 13 11:33:44 2010 -0500+++ b/model/TypeDef.cc Wed Dec 22 10:05:35 2010 -0500@@ -133,7 +133,8 @@ } FuncDefPtr TypeDef::createDefaultInit(Context &classContext) {- ContextPtr funcContext = classContext.createSubContext(Context::local);+ ContextPtr funcContext = classContext.createSubContext(Context::local,+ classContext.compileTime); // create the "this" variable ArgDefPtr thisDef = classContext.builder.createArgDef(this, "this");@@ -214,7 +215,8 @@ } void TypeDef::createDefaultDestructor(Context &classContext) {- ContextPtr funcContext = classContext.createSubContext(Context::local);+ ContextPtr funcContext = classContext.createSubContext(Context::local,+ classContext.compileTime); // create the "this" variable ArgDefPtr thisDef = classContext.builder.createArgDef(this, "this");@@ -247,7 +249,8 @@ } void TypeDef::createNewFunc(Context &classContext, FuncDef *initFunc) {- ContextPtr funcContext = classContext.createSubContext(Context::local);+ ContextPtr funcContext = classContext.createSubContext(Context::local,+ classContext.compileTime); funcContext->toplevel = true; funcContext->returnType = this;@@ -308,7 +311,8 @@ void TypeDef::createCast(Context &outer) { assert(hasVTable && "Attempt to createCast() on a non-virtual class");- ContextPtr funcCtx = outer.createSubContext(Context::local);+ ContextPtr funcCtx = outer.createSubContext(Context::local,+ outer.compileTime); funcCtx->toplevel = true; funcCtx->returnType = this;diff -r 5acf0c693bae parser/Parser.cc--- a/parser/Parser.cc Mon Dec 13 11:33:44 2010 -0500+++ b/parser/Parser.cc Wed Dec 22 10:05:35 2010 -0500@@ -205,7 +205,9 @@ // if we get an import keyword, parse the import statement. if (tok.isImport()) {- parseImportStmt(context->compileNS.get(), true);+ context->compileTime = true;+ parseImportStmt(context->compileNS.get());+ context->compileTime = false; return; }@@ -249,7 +251,7 @@ return context->getToplevel()->getParent(); } else if (tok.isImport()) { runCallbacks(controlStmt);- parseImportStmt(context->ns.get(), false);+ parseImportStmt(context->ns.get()); return 0; } else if (tok.isClass()) { if (!defsAllowed)@@ -531,7 +533,7 @@ ); } }-+cerr << "parse func call, compileTime: " << context->compileTime << "\n"; FuncCallPtr funcCall = context->builder.createFuncCall(func.get(), squashVirtual );@@ -1339,7 +1341,8 @@ TypeDef *classTypeDef = 0; // push a new context, arg defs will be stored in the new context.- ContextPtr subCtx = context->createSubContext(Context::local);+ ContextPtr subCtx = context->createSubContext(Context::local,+ context->compileTime); ContextStackFrame cstack(*this, subCtx.get()); context->returnType = returnType; context->toplevel = true;@@ -1938,7 +1941,7 @@ // import module-and-defs ; // ^ ^-void Parser::parseImportStmt(Namespace *ns, bool annotation) {+void Parser::parseImportStmt(Namespace *ns) { ModuleDefPtr mod; string canonicalName; Token tok = getToken();@@ -1947,7 +1950,9 @@ vector<string> moduleName; parseModuleName(moduleName); try {- mod = Crack::loadModule(moduleName, canonicalName, annotation);+ mod = Crack::loadModule(moduleName,+ canonicalName,+ context->compileTime); } catch (const spug::Exception &ex) { error(tok, ex.getMessage()); }@@ -2205,6 +2210,7 @@ new Context(context->builder, Context::instance, context.get(), 0, context->compileNS.get() );+ classContext->compileTime = context->compileTime; // emit the beginning of the class, hook it up to the class context and // store a reference to it in the parent context.@@ -2224,7 +2230,8 @@ NamespacePtr lexicalNS = new CompositeNamespace(type.get(), context->ns.get()); ContextPtr lexicalContext = - classContext->createSubContext(Context::composite, lexicalNS.get());+ classContext->createSubContext(Context::composite, context->compileTime,+ lexicalNS.get()); // push the new context ContextStackFrame cstack(*this, lexicalContext.get());@@ -2244,7 +2251,7 @@ toker(toker), moduleCtx(context), context(context) {- +cerr << "new parser, context compileTime: " << context->compileTime << "\n"; // build the precedence table enum { noPrec, logOrPrec, logAndPrec, bitOrPrec, bitXorPrec, bitAndPrec, cmpPrec, shiftPrec, addPrec, multPrec, unaryPrecdiff -r 5acf0c693bae parser/Parser.h--- a/parser/Parser.h Mon Dec 13 11:33:44 2010 -0500+++ b/parser/Parser.h Wed Dec 22 10:05:35 2010 -0500@@ -360,7 +360,7 @@ * Parse an import statement. 'ns' is the namespace in which to alias * imported symbols. */- void parseImportStmt(model::Namespace *ns, bool annotation);+ void parseImportStmt(model::Namespace *ns); /** * Parse a function definition after an "oper" keyword.