1 module sbylib.engine.project.moduleunit; 2 3 import std; 4 import sbylib.event; 5 import sbylib.engine.compiler.compiler; 6 import sbylib.engine.compiler.dll; 7 import sbylib.engine.compiler.exception; 8 import sbylib.engine.project.project; 9 import sbylib.engine.project.metainfo; 10 import sbylib.engine.project.modulecontext; 11 import sbylib.engine.project.modulestatus; 12 import sbylib.engine.promise; 13 14 class Module(RetType) { 15 private alias FuncType = RetType function(Project, ModuleContext); 16 17 const string path; 18 private ModuleContext _context; 19 private Project proj; 20 private DLL dll; 21 private ModuleStatusList statusList; 22 23 private FuncType func; 24 private string _name; 25 private string[] _dependencies; 26 27 this(Project proj, ModuleStatusList statusList, string path) { 28 this.proj = proj; 29 this.statusList = statusList; 30 this.path = path; 31 this._context = new ModuleContext; 32 33 this.status = ModuleStatus.Compiling; 34 Compiler.compile(path) 35 .error((Exception e) { 36 assert(this.status == ModuleStatus.Compiling); 37 this.status = tuple(ModuleStatus.CompileError, e.msg); 38 }) 39 .then((DLL dll) { 40 this.initFromDLL(dll); 41 assert(this.status == ModuleStatus.Compiling); 42 this.status = ModuleStatus.WaitingForRun; 43 44 when(dependencies.map!(d => proj.findPath(d)).all!(d => d != "" && statusList[d] == ModuleStatus.Running)).once({ 45 this.execute(proj); 46 }); 47 }); 48 } 49 50 ~this() { 51 if (this.status != ModuleStatus.Stopping) 52 this.stop(); 53 } 54 55 void stop() { 56 this.context.destroy(); 57 this.status = ModuleStatus.Stopping; 58 //this.dll.unload(); 59 } 60 61 private void initFromDLL(DLL dll) { 62 this.dll = dll; 63 64 auto getFunctionName = dll.loadFunction!(string function())("getFunctionName"); 65 auto functionName = getFunctionName(); 66 this.func = dll.loadFunction!(FuncType)(functionName); 67 68 auto getModuleName = dll.loadFunction!(string function())("getModuleName"); 69 this._name = getModuleName(); 70 71 auto getDependencies = dll.loadFunction!(string[] function())("getDependencies"); 72 this._dependencies = getDependencies(); 73 } 74 75 private void execute(Project proj) 76 in (status == ModuleStatus.WaitingForRun) 77 { 78 this.status = ModuleStatus.Running; 79 try { 80 context.bind(); 81 func(proj, context); 82 } catch (Exception e) { 83 assert(this.status == ModuleStatus.Running); 84 status = tuple(ModuleStatus.RuntimeError, e.toString()); 85 } 86 } 87 88 ModuleContext context() { 89 return _context; 90 } 91 92 private void status(T)(T t) { 93 statusList[path] = t; 94 } 95 96 private ModuleStatus status() const { 97 return statusList[path]; 98 } 99 100 package string name() const { return _name; } 101 package const(string[]) dependencies() const { return _dependencies; } 102 103 package string[] inputFiles() { 104 auto c = CompileConfig(path); 105 return c.mainFile ~ c.inputFiles; 106 } 107 }