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 }