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 +// XXX debug only +#include + 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 +// XXX debug only +#include + 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::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 // link in the JIT #include #include +#include #include #include @@ -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(m); + + if (crackMod->ctModule) { + // already bound + cerr << " already bound\n"; + return; + } + + if (m->fromExtension) { +cerr << "--jittin from extension " << m->getFullName() << "\n"; + for (map::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(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::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 &entries = targetVTable->entries; accomodate(entries, func->vtableSlot); - entries[func->vtableSlot] = (Constant*)func->getRep(*builder); + LLVMBuilder &b = dynamic_cast(context.builder); + entries[func->vtableSlot] = (Constant*)func->getRep(b, + context.compileTime); } // add the function to all vtables. @@ -72,7 +74,9 @@ ) { vector &entries = iter->second->entries; accomodate(entries, func->vtableSlot); - entries[func->vtableSlot] = (Constant*)func->getRep(*builder); + LLVMBuilder &b = dynamic_cast(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 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, unaryPrec diff -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.