private Tuple<VariableTreeDimension, ValueInfo> Handle_Expr_ArrayItem(XmlNode node)
{
VariableTreeDimension arrayKey;
var itemInfo = new ValueInfo();
var valueResult = Analyze(node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Value));
itemInfo.Taints = valueResult.ExpressionTaint;
if (valueResult.ValueInfo != null)
{
itemInfo = valueResult.ValueInfo.AssignmentClone();
}
var dimension = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Key);
Analyze(dimension);
// Start dimension resolving - This should probably be refactored!
var dimNode = dimension.GetSubNodesByPrefix(AstConstants.Node).SingleOrDefault();
// Rules:
// Strings with valid integers are cast
// Floats are cast to integer (fraction is truncated)
// Bools are cast to integers (true = 1, false = 0)
// Null = empty string
// Arrays/Objects cannot be used as key.
//
// Conflict - Last one wins.
if (dimNode == null)
{
arrayKey = new VariableTreeDimension()
{
Index = -1,
Key = "$UKENDT$"
};
}
else
{
if (dimNode.Name == AstConstants.Node + ":" + AstConstants.Nodes.Scalar_String)
{
var stringValue = ScalarNode.GetStringValue(dimNode);
arrayKey = new VariableTreeDimension() { Key = stringValue };
double indexValue;
if (double.TryParse(stringValue, out indexValue))
{
arrayKey.Index = (int)indexValue;
}
}
else if (dimNode.Name == AstConstants.Node + ":" + AstConstants.Nodes.Scalar_LNumber)
{
var index = ScalarNode.GetLValue(dimNode);
arrayKey = new VariableTreeDimension()
{
Index = index,
Key = index.ToString(CultureInfo.InvariantCulture)
};
}
else if (dimNode.Name == AstConstants.Node + ":" + AstConstants.Nodes.Scalar_DNumber)
{
var index = (int)ScalarNode.GetDValue(dimNode);
arrayKey = new VariableTreeDimension()
{
Index = index,
Key = index.ToString(CultureInfo.InvariantCulture)
};
}
else
{
// Default case. ie. Non resolvable dimension
arrayKey = new VariableTreeDimension()
{
Index = -1,
Key = "$UKENDT$"
};
}
}
// End dimension resolving.
return new Tuple<VariableTreeDimension, ValueInfo>(arrayKey, itemInfo);
}