All pastes #2027371 Raw Edit

crack

public diff v1 · immutable
#2027371 ·published 2010-12-23 17:16 UTC
rendered paste body
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.