tlang/source/tlang/compiler/typecheck/dependancy.d

427 lines
10 KiB
D

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);
}
}