private void _processVariables( ref IList<AbstractNode> nodes )
{
for ( int i = 0; i < nodes.Count; ++i )
{
AbstractNode cur = nodes[ i ];
if ( cur is ObjectAbstractNode )
{
// Only process if this object is not abstract
ObjectAbstractNode obj = (ObjectAbstractNode)cur;
if ( !obj.IsAbstract )
{
_processVariables( ref obj.Children );
_processVariables( ref obj.Values );
}
}
else if ( cur is PropertyAbstractNode )
{
PropertyAbstractNode prop = (PropertyAbstractNode)cur;
_processVariables( ref prop.Values );
}
else if ( cur is VariableGetAbstractNode )
{
VariableGetAbstractNode var = (VariableGetAbstractNode)cur;
// Look up the enclosing scope
ObjectAbstractNode scope = null;
AbstractNode temp = var.Parent;
while ( temp != null )
{
if ( temp is ObjectAbstractNode )
{
scope = (ObjectAbstractNode)temp;
break;
}
temp = temp.Parent;
}
// Look up the variable in the environment
KeyValuePair<bool, string> varAccess = new KeyValuePair<bool, string>( false, string.Empty );
if ( scope != null )
varAccess = scope.GetVariable( var.Name );
if ( scope == null || !varAccess.Key )
{
bool found = _environment.ContainsKey( var.Name );
if ( found )
varAccess = new KeyValuePair<bool, string>( true, _environment[ var.Name ] );
else
varAccess = new KeyValuePair<bool, string>( false, varAccess.Value );
}
if ( varAccess.Key )
{
// Found the variable, so process it and insert it into the tree
ScriptLexer lexer = new ScriptLexer();
IList<ScriptToken> tokens = lexer.Tokenize( varAccess.Value, var.File );
ScriptParser parser = new ScriptParser();
IList<ConcreteNode> cst = parser.ParseChunk( tokens );
IList<AbstractNode> ast = _convertToAST( cst );
// Set up ownership for these nodes
foreach ( AbstractNode currentNode in ast )
currentNode.Parent = var.Parent;
// Recursively handle variable accesses within the variable expansion
_processVariables( ref ast );
// Insert the nodes in place of the variable
for ( int j = 0; j < ast.Count; j++ )
nodes.Insert( j, ast[ j ] );
}
else
{
// Error
AddError( CompileErrorCode.UndefinedVariable, var.File, var.Line );
}
// Remove the variable node
nodes.RemoveAt( i );
i--;
}
}
}