public override object VisitExprApplyAttribute([NotNull] ChessVCParser.ExprApplyAttributeContext context) { object o = Visit(context.expression()); string attrname = context.ATTRIBUTE().GetText().Substring(1); Reference attr = globalIdentifierLookup(attrname); if (attr == null) { attrname += "Attribute"; attr = globalIdentifierLookup(attrname); if (attr == null) { throw new Exception("Attribute not defined: " + context.ATTRIBUTE().GetText()); } } // make sure object we found is of correct type if (!(attr.ReferencedObject is Type) || !(attr.ReferencedObject as Type).IsSubclassOf(typeof(Attribute))) { throw new Exception("Specified object is not an attribute: " + attrname); } // construct new object of attribute Type attrType = attr.ReferencedObject as Type; ConstructorInfo ci = attrType.GetConstructor(new Type[] { }); Attribute newAttr = (Attribute)ci.Invoke(null); if (o is ExObject) { (o as ExObject).AddAttribute(newAttr); } else if (o is Reference) { Reference r = (Reference)o; if (r.EffectiveType == typeof(ExObject) || r.EffectiveType.IsSubclassOf(typeof(ExObject))) { ((ExObject)r.GetValue()).AddAttribute(newAttr); } else if (r.EffectiveType == typeof(System.Type) || r.EffectiveType.IsSubclassOf(typeof(System.Type))) { // if the attribute is applied to a PieceType class (rather than an instance) then // we will try to construct an instance and apply the attribute to that. Type type = (Type)r.GetValue(); if (type.IsSubclassOf(typeof(PieceType))) { ConstructorInfo ci2 = type.GetConstructor(new Type[] { typeof(string), typeof(string), typeof(int), typeof(int), typeof(string) }); if (ci2 != null) { PieceType pt = (PieceType)ci2.Invoke(new object[] { null, null, 0, 0, null }); pt.AddAttribute(newAttr); // if the attribute is a PieceTypePropertyAttribute, we will apply it // to the move capabilities now. this is a temporary object and the // user is exepecting this to take effect (likely to pass this type // to the AddMoveOf function.) if (newAttr is PieceTypePropertyAttribute) { ((PieceTypePropertyAttribute)newAttr).AdjustMovement(pt); } return(pt); } } } } else { throw new Exception("Object of this type cannot be decorated with an attribute"); } return(o); }