module compiler.typecheck.dependancy; import gogga; import compiler.symbols.data; import compiler.symbols.typing.core; import compiler.typecheck.core; import std.conv : to; import compiler.parsing.core; public final class StructuralOrganizer { /* The associated TypeChecker */ private TypeChecker tc; private TreeNode root; this(TypeChecker tc) { this.tc = tc; } public void generate() { root = poolNode(tc.getModule()); checkContainer(tc.getModule()); } /** * Given a container this method will attempt to build * an implicit dependency tree (by setting the dependencies) * on the Entities contained within */ public void checkContainer(Container container) { /* Get all Entities */ Entity[] entities; foreach(Statement statement; container.getStatements()) { if(statement !is null && cast(Entity)statement) { entities ~= cast(Entity)statement; } } /** * Process entities */ foreach(Entity entity; entities) { /** * Variable declaration */ if(cast(Variable)entity) { /* Variable being declared */ Variable variable = cast(Variable)entity; /* Get the variable's type */ Type type = tc.getType(container, variable.getType()); /* If the variable has a class-type */ if(cast(Clazz)type) { /* Get the class-type */ Clazz classType = cast(Clazz)type; /* TODO: Ensure that we set dependences as A.B.C with A B C all static */ /* Statically initialize the class (make module depend on it) */ TreeNode classWalkInitDep = staticInitializeClass(classType); root.addDep(classWalkInitDep); /* Make the Module depend on this variable being initialized */ TreeNode varNode = poolNode(variable); root.addDep(varNode); } /* TODO: Handle assignment case */ if(variable.getAssignment()) { /* TODO: Implement me */ VariableAssignment varAssign = variable.getAssignment(); gprintln("Assignment: "~to!(string)(varAssign)); } } } } private TreeNode[] nodePool; public TreeNode poolNode(Entity entity) { foreach(TreeNode node; nodePool) { if(node.getEntity() == entity) { return node; } } TreeNode node = new TreeNode(tc, entity); nodePool ~= node; return node; } public bool isPooled(Entity entity) { foreach(TreeNode node; nodePool) { if(node.getEntity() == entity) { return true; } } return false; } /** * Statically initialize a class * * Outer class first then inner things * * TODO: Possible re-ordering would be needed */ public TreeNode staticInitializeClass(Clazz clazz) { /** * This is a recursive static initiliazer, all classes * must be static */ if(clazz.getModifierType() != InitScope.STATIC) { /** * All module-level classes are static (even though not marked as such) * * TODO: Add this into the parser code to seth this */ if(clazz.parentOf() != tc.getModule()) { Parser.expect("Cannot use a class type that is of a class that is non-static"); } } /** * This Class's TreeNode */ TreeNode treeNode; if(isPooled(clazz)) { treeNode = poolNode(clazz); return treeNode; // goto static_initialization_completed; } else { treeNode = poolNode(clazz); } /** * Check if the current Clazz has a parent Container * that is a Clazz, then go statically initialize that * first */ if(cast(Clazz)(clazz.parentOf())) { /* Statically initialize the parent class */ TreeNode parentNode = staticInitializeClass(cast(Clazz)(clazz.parentOf())); /* Set the child class to depend on the parent's static initialization */ treeNode.addDep(treeNode); } /* Get all Entities */ Entity[] entities; foreach(Statement statement; clazz.getStatements()) { if(statement !is null && cast(Entity)statement) { entities ~= cast(Entity)statement; } } /** * Process static entities * * Here we first want to mark the statics that have basic types * or non-basic class types that match our class */ foreach(Entity entity; entities) { if(entity.getModifierType() == InitScope.STATIC) { /** * Static Variable declarations */ if(cast(Variable)entity) { /* Variable being declared */ Variable variable = cast(Variable)entity; TreeNode variableTNode = poolNode(variable); /* Get the variable's type */ Type type = tc.getType(clazz, variable.getType()); /* If the variable's type basic */ if(cast(Primitive)type) { /* TODO: Init */ /* Immediately set as init, no further static recursion */ treeNode.addDep(variableTNode); } /* If the variable's type is class-type */ else if(cast(Clazz)type) { /* If it is ours */ if(type == clazz) { /* Immediately set as init, no further static recursion */ treeNode.addDep(variableTNode); } /* Else init the class AND then the variable */ else { treeNode.addDep(staticInitializeClass(cast(Clazz)type)); treeNode.addDep(variableTNode); } } else { /* TODO: dik */ } /* TODO: Implement this later */ if(variable.getAssignment()) { } } /* Static class definitions */ else if(cast(Clazz)entity) { /* Statically initialize the static class */ staticInitializeClass(cast(Clazz)entity); } } } static_initialization_completed: return treeNode; } /** * Given a `class A {}` this will make sure all static allocations * */ private void staticInitializeClass_reorder(Clazz) { } public void printPool() { foreach(TreeNode node; nodePool) { gprintln(node, DebugType.WARNING); } foreach(TreeNode node; nodePool) { figureOut(node); } gprintln("InitQueue: "~to!(string)(initQueue)); } public Entity[] initQueue; public void figureOut(TreeNode node) { /** * If there are no dependencies then * initialize it now (mark as completed) * and add to init queue */ if(!hasDeps(node)) { node.markCompleted(); initQueue ~= node.getEntity(); } /** * If there are dependencies then mark it * as busy */ else { node.markBusy(); /* Get the dependencies */ TreeNode[] nodeDeps = node.getDeps(); /** * */ foreach(TreeNode nodeDep; nodeDeps) { /* Initialize any non-busy node */ if(!nodeDep.isBusy()) { figureOut(nodeDep); } } } } public bool hasDeps(TreeNode node) { return cast(bool)node.getDeps().length; } /** * Given a path determine if it is accessible (in a static context) * * TODO: Explain * * If so, return the order of static initializations */ // public string[] } public class TreeNode { private Entity entity; private TreeNode[] deps; private TypeChecker tc; private bool isBusyB; private bool isCompletedB; public bool isCompleted() { return isCompletedB; } public void markCompleted() { isCompletedB = true; } public bool isBusy() { return isBusyB; } public void markBusy() { isBusyB = true; } this(TypeChecker tc, Entity entity) { this.entity = entity; this.tc = tc; } public void addDep(TreeNode node) { /* Only add if not already added */ foreach(TreeNode cNode; deps) { if(cNode == node) { return; } } deps ~= node; } public TreeNode isDep(Entity entity) { foreach(TreeNode node; deps) { if(node.getEntity() == entity) { return node; } } return null; } public Entity getEntity() { return entity; } public TreeNode[] getDeps() { return deps; } public override string toString() { string[] names; foreach(TreeNode node; deps) { names ~= tc.getResolver().generateName(tc.getModule(), node.getEntity()); } return "TreeNode ("~entity.getName()~"): "~to!(string)(names); } }