1 /// Author: Aziz Köksal
2 /// License: GPL3
3 /// $(Maturity low)
4 module dil.semantic.Pass;
5 
6 import dil.ast.DefaultVisitor,
7        dil.ast.Node,
8        dil.ast.Declarations,
9        dil.ast.Expressions,
10        dil.ast.Statements,
11        dil.ast.Types,
12        dil.ast.Parameters;
13 
14 /// Groups values and flags that provide (hierarchical) context
15 /// to the evaluation of a symbol.
16 class Scope
17 {
18 
19 }
20 
21 /// The Solver drives the semantic analysis.
22 /// It can register nodes whose analysis have been postponed.
23 class Solver
24 {
25   Node[Node] deps; /// Dependency set between nodes.
26   size_t doneCounter; /// The number of nodes resolved in this iteration.
27 
28   void run()
29   {
30     while (1) // The main loop.
31     {
32       doneCounter = 0;
33       // TODO: call visit() on nodes.
34       // Break if no more nodes could be resolved.
35       if (doneCounter == 0)
36         break;
37     }
38   }
39 
40   /// Node a waits for Node b to be resolved.
41   void depends(Node a, Node b, Scope sc)
42   { // TODO: save "sc" as well.
43     deps[a] = b;
44   }
45 
46   /// Called when a node has been resolved.
47   void onDone(Node n)
48   {
49     doneCounter++;
50   }
51 }
52 
53 /// Walks the tree and registers possible symbol declarations.
54 /// I.e.: functions/variables/aggregates/static if/is()
55 class DeclarationPass : DefaultVisitor
56 {
57 
58 }
59 
60 class MainSemanticPass : DefaultVisitor2
61 {
62   Solver sv;
63 
64   /// This function implements the core logic of the semantic evaluation.
65   ///
66   /// A node in the syntax tree may be revisited several times,
67   /// as it may have dependencies which have to be resolved first.
68   /// Every node has a state variable and depending on it
69   /// its analysis is deferred, stopped or finished.
70   ///
71   /// 1. If the node is already done or has an error the function returns.
72   /// 2. Otherwise every sub-node is visited.
73   /// 3. The evaluation stops prematurely if one of the sub-nodes has an error.
74   /// 4. When all sub-nodes are done, the node itself can be finished.
75   ///
76   /// Returns: true if n is in the Error or Done state.
77   bool errorOrWait(N)(N n)
78   {
79     if (n.error || n.done)
80       return true;
81 
82     bool hasError(Node child)
83     {
84       if (child.wait || child.finish)
85         visitN(child);
86       if (!child.error)
87         return false;
88       n.seterror(); // Propagate Error state to parent node.
89       return true;
90     }
91 
92     foreach (i, T; N.CTTI_Types)
93     { // auto child = n.memberName;
94       auto child = __traits(getMember, n, N.CTTI_Members[i]);
95       static if (is(T : Node)) // A Node?
96       { // Optionally check for null pointer. Return
97         if ((!CTTI_MayBeNull[i] || child !is null) && child.hasError())
98           return true;
99       }
100       else
101       static if (is(T : E[], E : Node)) // A Node array?
102       {
103         foreach (x; child)
104           if ((!CTTI_MayBeNull[i] || x !is null) && x.hasError())
105             return true;
106       }
107     }
108     n.setfinish();
109     return false; // No errors. The Node can be finished.
110   }
111 
112   override void visit(IntExpr n)
113   {
114     if (errorOrWait(n))
115       return;
116     // ...
117     if (0)
118       n.seterror(); // Error.
119     // ...
120     n.setdone();
121     sv.onDone(n);
122   }
123 }
124