- Removed old unused code
- Moved exceptions class for typechecker from `old/` to `typecheck/`
This commit is contained in:
parent
7224829fcb
commit
934bbb3b30
|
@ -1,595 +0,0 @@
|
|||
module compiler.typecheck.old.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()
|
||||
{
|
||||
/* Pool the Module */
|
||||
root = poolNode(tc.getModule());
|
||||
|
||||
/* Start checking from the Module-level */
|
||||
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);
|
||||
|
||||
|
||||
// }
|
||||
// /* If the variable has a basic type */
|
||||
// else if(cast(Primitive)type)
|
||||
// {
|
||||
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// assert(false);
|
||||
// }
|
||||
|
||||
// /* Make the Module depend on this variable being initialized */
|
||||
// TreeNode varNode = poolNode(variable);
|
||||
// root.addDep(varNode);
|
||||
|
||||
/* TODO: Use this new method */
|
||||
variableDeclare(container, variable);
|
||||
|
||||
// /* TODO: Handle assignment case */
|
||||
// if(variable.getAssignment())
|
||||
// {
|
||||
// /* TODO: Implement me */
|
||||
// VariableAssignment varAssign = variable.getAssignment();
|
||||
// gprintln("Assignment: "~to!(string)(varAssign));
|
||||
|
||||
// /* Get the Expression */
|
||||
// Expression assignmentExpression = varAssign.getExpression();
|
||||
|
||||
|
||||
// traceExpression(container, assignmentExpression);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check variable declaration relative to a container
|
||||
*/
|
||||
private void variableDeclare(Container rel, Variable variable)
|
||||
{
|
||||
/* Get the variable's type */
|
||||
Type type = tc.getType(rel, variable.getType());
|
||||
|
||||
|
||||
/**
|
||||
* If the variable declaration belongs to a Module
|
||||
*/
|
||||
if(cast(Module)rel)
|
||||
{
|
||||
/* If the variable has a basic type */
|
||||
if(cast(Primitive)type)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
/* If the variable has a class-type */
|
||||
else 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);
|
||||
}
|
||||
/* TODO: I shouldn't have anything here */
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* In any case we need to make the Module depend on this variable
|
||||
* (it must be initialized on module load)
|
||||
*/
|
||||
TreeNode varNode = poolNode(variable);
|
||||
root.addDep(varNode);
|
||||
}
|
||||
/*
|
||||
* If the variable declaration belongs to a Class
|
||||
*/
|
||||
else if(cast(Clazz)rel)
|
||||
{
|
||||
/* The Class */
|
||||
Clazz clazz = cast(Clazz)rel;
|
||||
|
||||
/* Static membership case */
|
||||
if(variable.getModifierType() == InitScope.STATIC)
|
||||
{
|
||||
/* Fetch the pooled Class TreeNode and Variable TreeNode */
|
||||
TreeNode classTreeNode = poolNode(clazz);
|
||||
TreeNode variableTreeNode = poolNode(variable);
|
||||
|
||||
/* If the variable's type basic */
|
||||
if(cast(Primitive)type)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
/* If the variable's type is class-type */
|
||||
else if(cast(Clazz)type)
|
||||
{
|
||||
/* If it is ours */
|
||||
if(type == clazz)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
/* Else init the class AND then the variable */
|
||||
else
|
||||
{
|
||||
/* Attempt to initialize all classes (all static) on the way) */
|
||||
classTreeNode.addDep(staticInitializeClass(cast(Clazz)type));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO: dik */
|
||||
assert(false);
|
||||
}
|
||||
|
||||
/* The class must depend on the static initialization of the variable (static member) */
|
||||
classTreeNode.addDep(variableTreeNode);
|
||||
|
||||
|
||||
/* TODO: Implement this later */
|
||||
if(variable.getAssignment())
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO: Implement me */
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Init orders?
|
||||
*/
|
||||
|
||||
private TreeNode traceExpression(Container rel, Expression exp)
|
||||
{
|
||||
TreeNode tnode;
|
||||
|
||||
/**
|
||||
* Simple VariableExpression
|
||||
* Exp: `a`
|
||||
*/
|
||||
if(cast(VariableExpression)exp)
|
||||
{
|
||||
/* Get the variable being referred to */
|
||||
Variable variableInExpression = cast(Variable)tc.getResolver().resolveBest(rel, (cast(VariableExpression)exp).getName());
|
||||
|
||||
|
||||
}
|
||||
else if(cast(Primitive)exp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
return tnode;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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())
|
||||
// {
|
||||
|
||||
// }
|
||||
|
||||
/* TODO: Use this new method */
|
||||
variableDeclare(clazz, variable);
|
||||
}
|
||||
/* Static class definitions */
|
||||
else if(cast(Clazz)entity)
|
||||
{
|
||||
/* Statically initialize the static class */
|
||||
TreeNode staticMemberClass = staticInitializeClass(cast(Clazz)entity);
|
||||
|
||||
/* We need to init it first as part of our initialization */
|
||||
treeNode.addDep(staticMemberClass);
|
||||
gprintln("brgfdfgdfgdu");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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("NodePOol"~to!(string)(nodePool));
|
||||
|
||||
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 and only
|
||||
* if it hasn't been added already
|
||||
*/
|
||||
if(!hasDeps(node))
|
||||
{
|
||||
if(!node.isCompleted())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add myself */
|
||||
node.markCompleted();
|
||||
initQueue ~= node.getEntity();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
module compiler.typecheck.old.group;
|
||||
|
||||
import gogga;
|
||||
import compiler.symbols.data;
|
||||
import compiler.symbols.typing.core;
|
||||
import compiler.typecheck.core;
|
||||
import std.conv : to;
|
||||
import compiler.parsing.core;
|
||||
|
||||
public class Group
|
||||
{
|
||||
private Container groupingEntity;
|
||||
private Entity[] initQueue;
|
||||
|
||||
this(Container groupingEntity, Entity[] initQueue)
|
||||
{
|
||||
this.groupingEntity = groupingEntity;
|
||||
this.initQueue = initQueue;
|
||||
}
|
||||
|
||||
public Container getGroupingEntity()
|
||||
{
|
||||
return groupingEntity;
|
||||
}
|
||||
|
||||
public Entity[] getInitQueue()
|
||||
{
|
||||
return initQueue;
|
||||
}
|
||||
|
||||
public override string toString()
|
||||
{
|
||||
return "GroupInit (" ~ (cast(Entity) groupingEntity)
|
||||
.getName() ~ "): " ~ to!(string)(initQueue);
|
||||
}
|
||||
}
|
||||
|
||||
public final class Grouper
|
||||
{
|
||||
// private TypeChecker tc;
|
||||
private Entity[] initQueue;
|
||||
private TypeChecker tc;
|
||||
|
||||
this(TypeChecker tc, Entity[] initQueue)
|
||||
{
|
||||
this.tc = tc;
|
||||
this.initQueue = initQueue;
|
||||
}
|
||||
|
||||
private Group[] groups;
|
||||
private Entity[][Container] containers;
|
||||
private Container[] keyOrder;
|
||||
|
||||
private void groupToContainer(Container entityContainer, Entity entityToContain)
|
||||
{
|
||||
foreach (Container container; keyOrder)
|
||||
{
|
||||
if (container == entityContainer)
|
||||
{
|
||||
goto add_to_container;
|
||||
}
|
||||
}
|
||||
|
||||
keyOrder ~= entityContainer;
|
||||
|
||||
add_to_container:
|
||||
containers[entityContainer] ~= entityToContain;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public Group[] begin()
|
||||
{
|
||||
gprintln("Grouping beginning...");
|
||||
gprintln("GBegin: "~to!(string)(initQueue));
|
||||
|
||||
foreach (Entity entity; initQueue)
|
||||
{
|
||||
/* The Container of the Entity */
|
||||
Container entityContainer = entity.parentOf();
|
||||
|
||||
/* Dont' add Module's container (which would be null) */
|
||||
if(entityContainer is null)
|
||||
{
|
||||
/* This should only ever occur whern the Entity is a Module */
|
||||
assert(cast(Module)entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
groupToContainer(entityContainer, entity);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Container container; keyOrder)
|
||||
{
|
||||
groups ~= new Group(container, containers[container]);
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
module compiler.typecheck.old.koporaal;
|
||||
|
||||
import gogga;
|
||||
import compiler.symbols.data;
|
||||
import compiler.symbols.typing.core;
|
||||
import compiler.typecheck.core;
|
||||
import std.conv : to;
|
||||
import compiler.parsing.core;
|
||||
import compiler.typecheck.old.group;
|
||||
|
||||
/**
|
||||
* Koporaal
|
||||
*
|
||||
* This is one step away from code generation, infact it almost is
|
||||
* but it won't emit code, rather follow the dependency tree
|
||||
*/
|
||||
public class Koporaal
|
||||
{
|
||||
/* The dependency tree */
|
||||
private Group[] groups;
|
||||
|
||||
this(Group[] groups)
|
||||
{
|
||||
this.groups = groups;
|
||||
}
|
||||
|
||||
private ulong i = 0;
|
||||
|
||||
public void printInit()
|
||||
{
|
||||
foreach(Group group; groups)
|
||||
{
|
||||
Entity[] entities = group.getInitQueue();
|
||||
foreach(Entity entity; entities)
|
||||
{
|
||||
gprintln("Initialize ("~to!(string)(i)~"): "~entity.getName());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
module compiler.typecheck.reliance;
|
||||
|
||||
import compiler.symbols.data;
|
||||
|
||||
/**
|
||||
* RelianceNode
|
||||
*
|
||||
* Represents a node in a tree saying which node
|
||||
* depends on what
|
||||
*/
|
||||
public final class RelianceNode
|
||||
{
|
||||
/* The Statement associated */
|
||||
private Statement statement;
|
||||
|
||||
/* Depends on */
|
||||
private RelianceNode[] dependancies;
|
||||
|
||||
/**
|
||||
* Creates a new RelianceNode with the
|
||||
* associated Statement
|
||||
*/
|
||||
this(Statement statement)
|
||||
{
|
||||
this.statement = statement;
|
||||
}
|
||||
|
||||
public void addDependancy(RelianceNode dependency)
|
||||
{
|
||||
dependancies ~= dependency;
|
||||
}
|
||||
|
||||
public RelianceNode[] getDependencies()
|
||||
{
|
||||
return dependancies;
|
||||
}
|
||||
|
||||
public Statement getStatement()
|
||||
{
|
||||
return statement;
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
module compiler.typecheck.visitor;
|
||||
|
||||
import compiler.symbols.data;
|
||||
|
||||
public final class VisitorTree
|
||||
{
|
||||
private VTreeNode root;
|
||||
|
||||
this(VTreeNode root)
|
||||
{
|
||||
this.root = root;
|
||||
}
|
||||
}
|
||||
|
||||
public final class VTreeNode
|
||||
{
|
||||
private VTreeNode[] children;
|
||||
private Statement statement;
|
||||
|
||||
this(Statement statement)
|
||||
{
|
||||
this.statement = statement;
|
||||
}
|
||||
|
||||
public void addChild(VTreeNode newChild)
|
||||
{
|
||||
children ~= newChild;
|
||||
}
|
||||
|
||||
public Statement getStatement()
|
||||
{
|
||||
return statement;
|
||||
}
|
||||
|
||||
public VTreeNode[] getChildren()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
|
||||
public VTreeNode isInTree(Statement statement)
|
||||
{
|
||||
/* If this node is the one being searched for */
|
||||
if(this.getStatement() == statement)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
/* If not */
|
||||
else
|
||||
{
|
||||
/* Get all this node's children */
|
||||
VTreeNode[] children = this.getChildren();
|
||||
|
||||
/* Make sure there are children */
|
||||
if(children.length)
|
||||
{
|
||||
/* Any of the children */
|
||||
foreach(VTreeNode child; children)
|
||||
{
|
||||
if(child.isInTree(statement))
|
||||
{
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
/* If above fails, then not found */
|
||||
return null;
|
||||
}
|
||||
/* If there are no children then not found */
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue