WIP: Dependency
This commit is contained in:
parent
28bbd68857
commit
d42779c3cc
|
@ -90,15 +90,8 @@ public final class TypeChecker
|
||||||
/* TODO: Process class ? vars funcs ?*/
|
/* TODO: Process class ? vars funcs ?*/
|
||||||
|
|
||||||
import compiler.typecheck.dependancy;
|
import compiler.typecheck.dependancy;
|
||||||
dependancyGenerate(this, modulle);
|
StructuralOrganizer so = new StructuralOrganizer(this);
|
||||||
|
so.checkContainer(modulle);
|
||||||
string depsString;
|
|
||||||
foreach(string key; keysOrder)
|
|
||||||
{
|
|
||||||
depsString ~= key~": "~to!(string)(deps[key])~", ";
|
|
||||||
}
|
|
||||||
gprintln("Final deps: "~to!(string)(depsString));
|
|
||||||
findEnd(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,353 +7,63 @@ import compiler.typecheck.core;
|
||||||
|
|
||||||
import std.conv : to;
|
import std.conv : to;
|
||||||
|
|
||||||
/**
|
public final class StructuralOrganizer
|
||||||
* A list of all the full-paths of entities and what they rely on
|
|
||||||
*
|
|
||||||
* TODO:
|
|
||||||
* So far we are looking at types and seeing what they depend on, not yet
|
|
||||||
* for assignments. When we get to assignments we should then add more
|
|
||||||
*/
|
|
||||||
public string[][string] deps;
|
|
||||||
|
|
||||||
public string[] keysOrder;
|
|
||||||
|
|
||||||
public void encounter(string entityName, string dependentOn)
|
|
||||||
{
|
{
|
||||||
if(entityName !in deps)
|
/* The associated TypeChecker */
|
||||||
|
private TypeChecker tc;
|
||||||
|
|
||||||
|
this(TypeChecker tc)
|
||||||
{
|
{
|
||||||
keysOrder ~= entityName;
|
this.tc = tc;
|
||||||
}
|
}
|
||||||
deps[entityName] ~= dependentOn;
|
|
||||||
gprintln("[Encounter] Entity: \""~entityName~"\" set to be dependent on \""~dependentOn~"\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void encounter(TypeChecker tc, Entity entityDependee, Entity dependentOn)
|
/* TODO: Return a list of Statement, in their init order */
|
||||||
{
|
public void checkContainer(Container container)
|
||||||
/* Full path of thing depending on something else */
|
|
||||||
string dependee = tc.getResolver().generateName(tc.getModule(), entityDependee);
|
|
||||||
|
|
||||||
/* Full path of the thing it is dependent on */
|
|
||||||
string dependency = tc.getResolver().generateName(tc.getModule(), dependentOn);
|
|
||||||
|
|
||||||
encounter(dependee, dependency);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a path to a class and a relative container to start at
|
|
||||||
* this will start at the top of the path and dependencyGneerate
|
|
||||||
* on each of them
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
*
|
|
||||||
* module j;
|
|
||||||
* A.B.C cInstance;
|
|
||||||
*
|
|
||||||
* class A
|
|
||||||
* {
|
|
||||||
* class B
|
|
||||||
* {
|
|
||||||
*
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* TODO: Implement me */
|
|
||||||
|
|
||||||
|
|
||||||
public bool hasDepChecked(TypeChecker tc, Entity entity)
|
|
||||||
{
|
|
||||||
/* Full path of the entity */
|
|
||||||
string entityFullPath = tc.getResolver().generateName(tc.getModule(), entity);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if it is in there
|
|
||||||
* TODO: Use `in`
|
|
||||||
*/
|
|
||||||
foreach(string key; deps.keys)
|
|
||||||
{
|
{
|
||||||
import std.string : cmp;
|
/* Get all Entities */
|
||||||
if(cmp(key, entityFullPath) == 0)
|
Entity[] entities;
|
||||||
|
foreach(Statement statement; container.getStatements())
|
||||||
{
|
{
|
||||||
return true;
|
if(statement !is null && cast(Entity)statement)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
import compiler.typecheck.reliance;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Statically initilizes a given class
|
|
||||||
*/
|
|
||||||
public void staticInitClass(TypeChecker tc, Clazz clazz)
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Don't init if we have initted before
|
|
||||||
*/
|
|
||||||
if(hasDepChecked(tc, clazz))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all Entities of the class that are static
|
|
||||||
*/
|
|
||||||
Entity[] staticEntities;
|
|
||||||
foreach (Statement statement; clazz.getStatements())
|
|
||||||
{
|
|
||||||
if (statement !is null && cast(Entity) statement)
|
|
||||||
{
|
|
||||||
Entity entity = cast(Entity)statement;
|
|
||||||
if(entity.getModifierType() == InitScope.STATIC)
|
|
||||||
{
|
{
|
||||||
staticEntities ~= cast(Entity) statement;
|
entities ~= cast(Entity)statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process the static members
|
|
||||||
*/
|
|
||||||
foreach(Entity staticMember; staticEntities)
|
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* If the static member is a variable
|
* Process entities
|
||||||
* declaration
|
|
||||||
*/
|
*/
|
||||||
if(cast(Variable)staticMember)
|
foreach(Entity entity; entities)
|
||||||
{
|
|
||||||
Variable variable = cast(Variable)staticMember;
|
|
||||||
|
|
||||||
/* Get the variable's type */
|
|
||||||
Type variableType = tc.getType(clazz, variable.getType());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the type is a class type
|
|
||||||
*/
|
|
||||||
if(cast(Clazz)variableType)
|
|
||||||
{
|
|
||||||
Clazz classType = cast(Clazz)variableType;
|
|
||||||
|
|
||||||
/* Static initialize the class if it is not this class-type */
|
|
||||||
if(classType != clazz)
|
|
||||||
{
|
|
||||||
/* Set this class to be dependent on the class of the class-type */
|
|
||||||
encounter(tc, clazz, classType);
|
|
||||||
|
|
||||||
/* Initialize (statically) the class referred to by the class-type */
|
|
||||||
staticInitClass(tc, classType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* This class depends on this variable being initialized */
|
|
||||||
encounter(tc, clazz, variable);
|
|
||||||
|
|
||||||
/* If then variable has an assignment */
|
|
||||||
if(variable.getAssignment())
|
|
||||||
{
|
|
||||||
/* TODO: Add assignment support */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
encounter(tc, staticMember, staticMember);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool isClassMember(TypeChecker tc, Clazz c, string memberName)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string findEnd(TypeChecker tc)
|
|
||||||
{
|
|
||||||
string end;
|
|
||||||
|
|
||||||
foreach(string entityPath; deps.keys)
|
|
||||||
{
|
|
||||||
string[] dependencies = deps[entityPath];
|
|
||||||
|
|
||||||
foreach(string dependency; dependencies)
|
|
||||||
{
|
|
||||||
/* Check if the dependency has only itself */
|
|
||||||
string visitedNode = dependency;
|
|
||||||
string[] visistedNodeDependencies = deps[visitedNode];
|
|
||||||
|
|
||||||
/* If only one dep, add to top of init queue */
|
|
||||||
if(visistedNodeDependencies.length == 1)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach(string vNodeDep; visistedNodeDependencies)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return end;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void virtualInitClass(TypeChecker tc, Clazz clazz)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the path downwards is all static dentities
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void dependancyGenerate(TypeChecker tc, Container container)
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The Container Entity
|
|
||||||
*/
|
|
||||||
Entity containerEntity = cast(Entity)container;
|
|
||||||
assert(containerEntity);
|
|
||||||
string containerEntityName = tc.getResolver().generateName(tc.getModule(), containerEntity);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all Entities
|
|
||||||
*/
|
|
||||||
Entity[] containerEntities;
|
|
||||||
foreach (Statement statement; container.getStatements())
|
|
||||||
{
|
|
||||||
if (statement !is null && cast(Entity) statement)
|
|
||||||
{
|
|
||||||
containerEntities ~= cast(Entity) statement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gprintln("[dependencyGenerate] Container: \""~containerEntityName~"\" has the following members:\n\n"~to!(string)(containerEntities));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process all entities
|
|
||||||
*
|
|
||||||
* The natural order would be classes, funcitons/variables (I cannot remember TOOD: check this)
|
|
||||||
*
|
|
||||||
* If, for example, we have `A aInstance;` as a module-level variable declaration then
|
|
||||||
* we must statically initialize A (the class as that is a class-type reference) - we do
|
|
||||||
* this by visiting the class and initializing all of it's things
|
|
||||||
*/
|
|
||||||
foreach(Entity entity; containerEntities)
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* If we are at Module level then things differ
|
|
||||||
* ever so slightly
|
|
||||||
*/
|
|
||||||
if(container == tc.getModule())
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* If we have a module-level variable declaration then we want to check
|
* Variable declaration
|
||||||
* if the type of the variable being declared is:
|
|
||||||
*
|
|
||||||
* 1. Basic (int, float, etc.)
|
|
||||||
* - Then we will do nothing, it is not dependent
|
|
||||||
* 2. Non-basic (Class-case only)
|
|
||||||
* - Then we will check if that class is accessible
|
|
||||||
* 1. If it is at the module-level then it is implied static so it would be
|
|
||||||
* 2. If at a level deeper then more care must be taken
|
|
||||||
*
|
|
||||||
* TODO: Assignments still not supported as this means more checking
|
|
||||||
*/
|
*/
|
||||||
if(cast(Variable)entity)
|
if(cast(Variable)entity)
|
||||||
{
|
{
|
||||||
|
/* Variable being declared */
|
||||||
Variable variable = cast(Variable)entity;
|
Variable variable = cast(Variable)entity;
|
||||||
|
|
||||||
/* Get the variable's type */
|
/* Get the variable's type */
|
||||||
Type variableType = tc.getType(container, variable.getType());
|
Type type = tc.getType(container, variable.getType());
|
||||||
|
|
||||||
/**
|
/* If the variable has a class-type */
|
||||||
* Check if the type is a class type
|
if(cast(Clazz)type)
|
||||||
*/
|
|
||||||
if(cast(Clazz)variableType)
|
|
||||||
{
|
{
|
||||||
Clazz classType = cast(Clazz)variableType;
|
/* Get the class-type */
|
||||||
|
Clazz classType = cast(Clazz)type;
|
||||||
|
|
||||||
/* If the class is defined at the module-level then it is static by default */
|
/* TODO: Ensure that we set dependences as A.B.C with A B C all static */
|
||||||
if(classType.parentOf() == tc.getModule())
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Then mark the class as a dependency (the class-name/type reference)
|
|
||||||
* must cause the static initialization to go off
|
|
||||||
*
|
|
||||||
* module pp;
|
|
||||||
* Person k;
|
|
||||||
* class Person { }
|
|
||||||
*
|
|
||||||
* Above it means that because the type of `k` is `Person` and that is a
|
|
||||||
* class type therefore the Person class should have its static constructor
|
|
||||||
* run (=> all static members should be initialized)
|
|
||||||
*
|
|
||||||
* Okay, so we do all of the above SECOND, first the class must be checked itself
|
|
||||||
*/
|
|
||||||
staticInitClass(tc, classType);
|
|
||||||
encounter(tc, variable, classType);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* TODO: Possible errors but may work too */
|
|
||||||
gprintln("Woah there cowboy, this is dangerous territory", DebugType.WARNING);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Anything else (TODO: Checking)
|
|
||||||
*/
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* TODO: EVerything else is fine */
|
|
||||||
/* TODO: Either struct or primtive, neither have static initlization */
|
|
||||||
|
|
||||||
/* We need to still know it exists */
|
|
||||||
encounter(tc, variable, variable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If then variable has an assignment */
|
|
||||||
|
/* TODO: Handle assignment case */
|
||||||
if(variable.getAssignment())
|
if(variable.getAssignment())
|
||||||
{
|
{
|
||||||
/* TODO: Add assignment support */
|
/* TODO: Implement me */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* If we are at the Class level
|
|
||||||
*/
|
|
||||||
else if(cast(Clazz)container)
|
|
||||||
{
|
|
||||||
/* TODO: Only should be called in static-initialization case */
|
|
||||||
// Clazz clazz = cast(Clazz)container;
|
|
||||||
// assert(clazz.);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* If we are at the Struct level
|
|
||||||
*/
|
|
||||||
else if(cast(Struct)container)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Any other type of Container
|
|
||||||
*/
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* This shouldn't happen */
|
|
||||||
gprintln("BAAD", DebugType.ERROR);
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue