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