Skip to content

Commit

Permalink
CodeContracts OCL Runtime
Browse files Browse the repository at this point in the history
- fixed tuple equality
  • Loading branch information
dort committed Jul 26, 2013
1 parent 6998a95 commit d1d1c93
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 48 deletions.
2 changes: 1 addition & 1 deletion CodeContractsSupport/OclCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public virtual OclSet product(OclCollection c2)
OclSet set = new OclSet(newElementType);
foreach (OclAny e1 in this)
foreach (OclAny e2 in c2)
set.set.Add(new OclTuple(newElementType, e1, e2));
set.set.Add(new OclTuple(newElementType, OclTuple.Part("first",e1), OclTuple.Part("second",e2)));
return set;
}

Expand Down
48 changes: 25 additions & 23 deletions CodeContractsSupport/OclTuple.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ namespace Exolutio.CodeContracts.Support
{
public class OclTuple : OclAny, IEquatable<OclTuple>
{
private OclTupleType type;
private OclAny[] parts;
private readonly OclTupleType type;
private readonly Dictionary<string, OclAny> parts = new Dictionary<string, OclAny>();

public struct TuplePart
{
Expand All @@ -21,23 +21,29 @@ public static TuplePart Part(string name, OclClassifier type, OclAny value)
{
return new TuplePart { name = name, type = type, value = value };
}

#region Constructors
/// <summary>
/// Create tuple of the specified type and with the specified values.
/// </summary>
/// <param name="type">Type of the whole tuple</param>
/// <param name="parts">Individual values</param>
public OclTuple(OclTupleType type, params OclAny[] parts)
public static TuplePart Part(string name, OclAny value)
{
this.parts = parts;
this.type = type;
return new TuplePart { name = name, type = null, value = value };
}


#region Constructors

public OclTuple(params TuplePart[] parts)
{
this.parts = (from x in parts select x.value).ToArray();
this.type = OclTupleType.Tuple((from x in parts select OclTupleType.Part(x.name, x.type)).ToArray());
if(parts == null)
throw new ArgumentNullException();
foreach (var part in parts)
this.parts[part.name] = part.value;
this.type = OclTupleType.Tuple(from x in parts select OclTupleType.Part(x.name, x.type));
}
public OclTuple(OclTupleType type, params TuplePart[] parts)
{
if (type == null || parts == null)
throw new ArgumentNullException();
foreach (var part in parts)
this.parts[part.name] = part.value;
this.type = type;
}
#endregion

Expand All @@ -52,28 +58,24 @@ public bool Equals(OclTuple obj)
if (!obj.type.Equals(type))
return false;
//Compare elements
return Enumerable.SequenceEqual(parts, obj.parts);
return parts.All(part => obj.parts[part.Key].Equals(part.Value));

}
public override int GetHashCode()
{
unchecked
{
int code = type.GetHashCode();
foreach (OclAny a in parts)
code = code * 13 + a.GetHashCode();
foreach (KeyValuePair<string, OclAny> part in parts)
code = part.Value.GetHashCode();
return code;
}
}

#endregion
public T Get<T>(string element) where T : OclAny
{
return (T)parts[type.nameToIndex(element)];
}
public T Get<T>(int index) where T : OclAny
{
return (T)parts[index];
return (T)parts[element];
}

public override OclClassifier oclType()
Expand Down
60 changes: 36 additions & 24 deletions CodeContractsSupport/Types/OclTupleType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,39 @@ public static OclTuplePart Part(string name, OclClassifier type){
}
public static OclTupleType Tuple(params OclTuplePart[] parts)
{
return new OclTupleType(parts);//TODO: cache
return new OclTupleType(parts);
}
public static OclTupleType Tuple(IEnumerable<OclTuplePart> parts)
{
return new OclTupleType(parts);
}
#endregion
private readonly OclTuplePart[] parts;
private readonly Dictionary<string, OclClassifier> parts = new Dictionary<string, OclClassifier>();

private OclTupleType(params OclTuplePart[] parts)
private OclTupleType(IEnumerable<OclTuplePart> parts)
{
this.parts = parts;
foreach (OclTuplePart part in parts)
this.parts[part.name] = part.type;
}

#region Equality
public bool Equals(OclTupleType other)
{
if (other == null)
return false;
return Enumerable.SequenceEqual(parts, other.parts);
//The type must have same number of parts
if (other.parts.Count != parts.Count)
return false;
//Every part from this type must be in the other type and have the same type
foreach (var part in parts)
{
OclClassifier partType;
if (!other.parts.TryGetValue(part.Key, out partType))
return false;
if (!part.Value.Equals(partType))
return false;
}
return true;
}
public override bool Equals(object obj)
{
Expand All @@ -74,8 +91,9 @@ public override int GetHashCode()
{
unchecked{
int code = 0;
foreach (OclTuplePart tp in parts)
code = code * 17 + tp.GetHashCode();
//Combine hash codes of part names and types
foreach (KeyValuePair<string, OclClassifier> tp in parts)
code += tp.Key.GetHashCode() + 11*tp.Value.GetHashCode();
return code;
}
}
Expand All @@ -90,31 +108,25 @@ internal override bool ConformsToInternal(OclClassifier cls)
{
//Tuple conforms to another tuple if they have parts of same names and order and conforming types
OclTupleType tt = (OclTupleType)cls;
if (tt.parts.Length != parts.Length)
if (tt.parts.Count != parts.Count)
return false;
else
{
return !tt.parts.Where((t, i) => !parts[i].conformsTo(t)).Any();
//Each tuple part typ must conform to the corresponding part type
foreach (var part in parts)
{
OclClassifier partType;
if (!tt.parts.TryGetValue(part.Key, out partType))
return false;
if (!part.Value.ConformsToInternal(partType))
return false;
}
return true;
}
}
else
return false;
}

/// <summary>
/// Convert tuple part name to part index
/// </summary>
/// <param name="name">Part name. The name must be valid.</param>
/// <returns>Zero-based index of the tuple part.</returns>
internal int nameToIndex(string name){
for (int i = 0; i < parts.Length; ++i)
{
if (parts[i].name == name)
return i;
}
throw new ArgumentException();
}


}

Expand Down

0 comments on commit d1d1c93

Please sign in to comment.