using System;
using System.Diagnostics;
using System.Collections;
+using System.Collections.Specialized;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
namespace Mono.MonoBASIC {
+ /// <summary>
+ /// Base class for objects that can have Attributes applied to them.
+ /// </summary>
+ public abstract class Attributable {
+ /// <summary>
+ /// Attributes for this type
+ /// </summary>
+ Attributes attributes;
+
+ public Attributable(Attributes attrs)
+ {
+ attributes = attrs;
+ }
+
+ public Attributes OptAttributes
+ {
+ get {
+ return attributes;
+ }
+ set {
+ attributes = value;
+ }
+ }
+
+ /// <summary>
+ /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
+ /// </summary>
+ public abstract void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb);
+ /// <summary>
+ /// Returns one AttributeTarget for this element.
+ /// </summary>
+ public abstract AttributeTargets AttributeTargets { get; }
+ };
public class Attribute {
+ public readonly string ExplicitTarget;
public readonly string Name;
public readonly ArrayList Arguments;
- Location Location;
+ public Location Location;
public Type Type;
-
- //
- // The following are only meaningful when the attribute
- // being emitted is one of the builtin ones
- //
- AttributeTargets Targets;
- bool AllowMultiple;
- bool Inherited;
- bool UsageAttr = false;
+ // Is non-null if type is AttributeUsageAttribute
+ AttributeUsageAttribute usage_attribute;
+
+ public AttributeUsageAttribute UsageAttribute {
+ get {
+ return usage_attribute;
+ }
+ }
+
+ bool usage_attr = false;
MethodImplOptions ImplOptions;
- UnmanagedType UnmanagedType;
+ public UnmanagedType UnmanagedType;
CustomAttributeBuilder cb;
-
+
public Attribute (string name, ArrayList args, Location loc)
{
Name = name;
Arguments = args;
Location = loc;
}
+
+ public Attribute (string target, string name, ArrayList args, Location loc)
+ {
+ ExplicitTarget = target;
+ }
void Error_InvalidNamedArgument (string name)
{
" missing a using directive or an assembly reference ?)");
return null;
}
+
public Type ResolveType (EmitContext ec)
{
bool MethodImplAttr = false;
bool MarshalAsAttr = false;
- UsageAttr = false;
+ usage_attr = false;
if (Type == TypeManager.attribute_usage_type)
- UsageAttr = true;
+ usage_attr = true;
if (Type == TypeManager.methodimpl_attr_type)
MethodImplAttr = true;
if (Type == TypeManager.marshal_as_attr_type)
return null;
}
- if (UsageAttr)
- this.Targets = (AttributeTargets) pos_values [0];
+ if (usage_attr)
+ usage_attribute = new AttributeUsageAttribute ((AttributeTargets) pos_values [0]);
if (MethodImplAttr)
this.ImplOptions = (MethodImplOptions) pos_values [0];
object o = ((Constant) e).GetValue ();
prop_values.Add (o);
- if (UsageAttr) {
+ if (usage_attr) {
if (member_name == "AllowMultiple")
- this.AllowMultiple = (bool) o;
+ usage_attribute.AllowMultiple = (bool) o;
if (member_name == "Inherited")
- this.Inherited = (bool) o;
+ usage_attribute.Inherited = (bool) o;
}
} else if (e is TypeOf) {
return cb;
}
- static string GetValidPlaces (Attribute attr)
+ public string GetValidTargets ()
{
StringBuilder sb = new StringBuilder ();
- AttributeTargets targets = 0;
-
- TypeContainer a = TypeManager.LookupAttr (attr.Type);
-
- if (a == null) {
-
- System.Attribute [] attrs = null;
-
- try {
- attrs = System.Attribute.GetCustomAttributes (attr.Type);
-
- } catch {
- Report.Error (-20, attr.Location, "Cannot find attribute type " + attr.Name +
- " (maybe you forgot to set the usage using the" +
- " AttributeUsage attribute ?).");
- return null;
- }
-
- foreach (System.Attribute tmp in attrs)
- if (tmp is AttributeUsageAttribute) {
- targets = ((AttributeUsageAttribute) tmp).ValidOn;
- break;
- }
- } else
- targets = a.Targets;
-
+ AttributeTargets targets = GetAttributeUsage ().ValidOn;
if ((targets & AttributeTargets.Assembly) != 0)
sb.Append ("'assembly' ");
Report.Error (
592, loc, "Attribute '" + a.Name +
"' is not valid on this declaration type. " +
- "It is valid on " + GetValidPlaces (a) + "declarations only.");
+ "It is valid on " + a.GetValidTargets () + "declarations only.");
}
public static bool CheckAttribute (Attribute a, object element)
{
- TypeContainer attr = TypeManager.LookupAttr (a.Type);
- AttributeTargets targets = 0;
-
-
- if (attr == null) {
+ //TypeContainer attr = TypeManager.LookupClass (a.Type);
+ AttributeTargets targets = a.GetAttributeUsage ().ValidOn;
- System.Attribute [] attrs = null;
-
- try {
- attrs = System.Attribute.GetCustomAttributes (a.Type);
-
- } catch {
- Report.Error (-20, a.Location, "Cannot find attribute type " + a.Name +
- " (maybe you forgot to set the usage using the" +
- " AttributeUsage attribute ?).");
- return false;
- }
-
- foreach (System.Attribute tmp in attrs)
- if (tmp is AttributeUsageAttribute)
- targets = ((AttributeUsageAttribute) tmp).ValidOn;
- } else
- targets = attr.Targets;
if (element is Class) {
if ((targets & AttributeTargets.Class) != 0)
return true;
else
return false;
- } else if (element is Event || element is InterfaceEvent) {
+ } else if (element is Event /*|| element is InterfaceEvent*/) {
if ((targets & AttributeTargets.Event) != 0)
return true;
else
return true;
else
return false;
- } else if (element is Method || element is Operator || element is InterfaceMethod || element is Accessor) {
+ } else if (element is Method || element is Accessor) {
if ((targets & AttributeTargets.Method) != 0)
return true;
else
return true;
else
return false;
- } else if (element is Property || element is Indexer ||
- element is InterfaceProperty || element is InterfaceIndexer) {
+ } else if (element is Property /* || element is Indexer ||
+ element is InterfaceProperty || element is InterfaceIndexer*/) {
if ((targets & AttributeTargets.Property) != 0)
return true;
else
return true;
else
return false;
- }
+ } else if (element is ModuleBuilder){
+ if ((targets & AttributeTargets.Module) != 0)
+ return true;
+ else
+ return false;
+ }
return false;
}
+ /// <summary>
+ /// Returns AttributeUsage attribute for this type
+ /// </summary>
+ public AttributeUsageAttribute GetAttributeUsage ()
+ {
+ Class attr_class = (Class) TypeManager.LookupClass (Type);
+
+ if (attr_class == null) {
+ object[] usage_attr = Type.GetCustomAttributes (TypeManager.attribute_usage_type, true);
+ return (AttributeUsageAttribute)usage_attr [0];
+ }
+
+ return attr_class.AttributeUsage;
+ }
+
//
- // This method should be invoked to pull the IndexerName attribute from an
+ // This method should be invoked to pull the DefaultPropName attribute from an
// Indexer if it exists.
//
public static string ScanForIndexerName (EmitContext ec, Attributes opt_attrs)
{
if (opt_attrs == null)
return null;
- if (opt_attrs.AttributeSections == null)
- return null;
-
- foreach (AttributeSection asec in opt_attrs.AttributeSections) {
- if (asec.Attributes == null)
- continue;
- foreach (Attribute a in asec.Attributes){
- if (a.ResolveType (ec) == null)
- return null;
+ foreach (Attribute a in opt_attrs.Attrs) {
+ if (a.ResolveType (ec) == null)
+ return null;
- if (a.Type != TypeManager.indexer_name_type)
- continue;
+ if (a.Type != TypeManager.indexer_name_type)
+ continue;
- //
- // So we have found an IndexerName, pull the data out.
- //
- if (a.Arguments == null || a.Arguments [0] == null){
- Error_AttributeConstructorMismatch (a.Location);
- return null;
- }
- ArrayList pos_args = (ArrayList) a.Arguments [0];
- if (pos_args.Count == 0){
- Error_AttributeConstructorMismatch (a.Location);
- return null;
- }
+ //
+ // So we have found an DefaultPropName, pull the data out.
+ //
+ if (a.Arguments == null || a.Arguments [0] == null){
+ Error_AttributeConstructorMismatch (a.Location);
+ return null;
+ }
+ ArrayList pos_args = (ArrayList) a.Arguments [0];
+ if (pos_args.Count == 0){
+ Error_AttributeConstructorMismatch (a.Location);
+ return null;
+ }
- Argument arg = (Argument) pos_args [0];
- if (!arg.Resolve (ec, a.Location))
- return null;
+ Argument arg = (Argument) pos_args [0];
+ if (!arg.Resolve (ec, a.Location))
+ return null;
- Expression e = arg.Expr;
- if (!(e is StringConstant)){
- Error_AttributeConstructorMismatch (a.Location);
- return null;
- }
+ Expression e = arg.Expr;
+ if (!(e is StringConstant)){
+ Error_AttributeConstructorMismatch (a.Location);
+ return null;
+ }
- //
- // Remove the attribute from the list
- //
- asec.Attributes.Remove (a);
+ //
+ // Remove the attribute from the list
+ //
+ opt_attrs.Attrs.Remove (a);
- return (((StringConstant) e).Value);
- }
+ return (((StringConstant) e).Value);
}
return null;
}
return ((StringConstant) arg.Expr).Value;
}
+
+ /// <summary>
+ /// Emit attribute for Attributable symbol
+ /// </summary>
+ public void Emit (EmitContext ec, Attributable ias, ListDictionary emitted_attr)
+ {
+ CustomAttributeBuilder cb = Resolve (ec);
+ if (cb == null)
+ return;
+
+ AttributeUsageAttribute usage_attr = GetAttributeUsage ();
+ if ((usage_attr.ValidOn & ias.AttributeTargets) == 0) {
+ Report.Error (592, Location, "Attribute" + Name + "is not valid on this declaration type. It is valid on " + GetValidTargets () + " declarations only.");
+ return;
+ }
+
+ ias.ApplyAttributeBuilder (this, cb);
+ }
+
//
// Applies the attributes to the `builder'.
//
{
if (opt_attrs == null)
return;
- if (opt_attrs.AttributeSections == null)
- return;
- foreach (AttributeSection asec in opt_attrs.AttributeSections) {
- if (asec.Attributes == null)
- continue;
+ foreach (Attribute a in opt_attrs.Attrs) {
+ CustomAttributeBuilder cb = a.Resolve (ec);
- if (asec.Target == "assembly" && !(builder is AssemblyBuilder))
+ if (cb == null)
continue;
-
- foreach (Attribute a in asec.Attributes) {
- CustomAttributeBuilder cb = a.Resolve (ec);
-
- if (cb == null)
- continue;
- if (!(kind is TypeContainer))
- if (!CheckAttribute (a, kind)) {
+ if (!(kind is TypeContainer))
+ if (!CheckAttribute (a, kind)) {
Error_AttributeNotValidForElement (a, loc);
return;
- }
+ }
- if (kind is Method || kind is Operator || kind is InterfaceMethod ||
- kind is Accessor) {
- if (a.Type == TypeManager.methodimpl_attr_type) {
- if (a.ImplOptions == MethodImplOptions.InternalCall)
- ((MethodBuilder) builder).
- SetImplementationFlags (
- MethodImplAttributes.InternalCall |
- MethodImplAttributes.Runtime);
- } else if (a.Type != TypeManager.dllimport_type){
+ if (kind is Method || kind is Accessor) {
+ if (a.Type == TypeManager.methodimpl_attr_type) {
+ if (a.ImplOptions == MethodImplOptions.InternalCall)
+ ((MethodBuilder) builder).SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
+ } else if (a.Type != TypeManager.dllimport_type){
((MethodBuilder) builder).SetCustomAttribute (cb);
- }
- } else if (kind is Constructor) {
- ((ConstructorBuilder) builder).SetCustomAttribute (cb);
- } else if (kind is Field) {
- ((FieldBuilder) builder).SetCustomAttribute (cb);
- } else if (kind is Property || kind is Indexer ||
- kind is InterfaceProperty || kind is InterfaceIndexer) {
- ((PropertyBuilder) builder).SetCustomAttribute (cb);
- } else if (kind is Event || kind is InterfaceEvent) {
- ((MyEventBuilder) builder).SetCustomAttribute (cb);
- } else if (kind is ParameterBuilder) {
-
- if (a.Type == TypeManager.marshal_as_attr_type) {
- UnmanagedMarshal marshal =
- UnmanagedMarshal.DefineUnmanagedMarshal (a.UnmanagedType);
-
- ((ParameterBuilder) builder).SetMarshal (marshal);
- } else
- ((ParameterBuilder) builder).SetCustomAttribute (cb);
-
- } else if (kind is Enum) {
- ((TypeBuilder) builder).SetCustomAttribute (cb);
-
- } else if (kind is TypeContainer) {
- TypeContainer tc = (TypeContainer) kind;
-
- if (a.UsageAttr) {
- tc.Targets = a.Targets;
- tc.AllowMultiple = a.AllowMultiple;
- tc.Inherited = a.Inherited;
-
- } else if (a.Type == TypeManager.default_member_type) {
- if (tc.Indexers != null) {
- Report.Error (646, loc,
- "Cannot specify the DefaultMember attribute on" +
- " a type containing an indexer");
- return;
- }
-
- } else {
- if (!CheckAttribute (a, kind)) {
- Error_AttributeNotValidForElement (a, loc);
- return;
- }
- }
-
- try {
- ((TypeBuilder) builder).SetCustomAttribute (cb);
- } catch (System.ArgumentException) {
- Report.Warning (
- -21, loc,
- "The CharSet named property on StructLayout\n"+
- "\tdoes not work correctly on Microsoft.NET\n"+
- "\tYou might want to remove the CharSet declaration\n"+
- "\tor compile using the Mono runtime instead of the\n"+
- "\tMicrosoft .NET runtime");
- }
-
- } else if (kind is Interface) {
- Interface iface = (Interface) kind;
-
- if ((a.Type == TypeManager.default_member_type) &&
- (iface.InterfaceIndexers != null)) {
- Report.Error (
- 646, loc,
- "Cannot specify the DefaultMember attribute on" +
- " a type containing an indexer");
- return;
- }
-
- if (!CheckAttribute (a, kind)) {
- Error_AttributeNotValidForElement (a, loc);
- return;
- }
-
- ((TypeBuilder) builder).SetCustomAttribute (cb);
- } else if (kind is AssemblyBuilder){
- ((AssemblyBuilder) builder).SetCustomAttribute (cb);
- } else if (kind is ModuleBuilder) {
- ((ModuleBuilder) builder).SetCustomAttribute (cb);
- } else if (kind is FieldBuilder) {
- ((FieldBuilder) builder).SetCustomAttribute (cb);
- } else
- throw new Exception ("Unknown kind: " + kind);
- }
+ }
+ } else
+ throw new Exception ("Unknown kind: " + kind);
}
}
CallingConvention cc = CallingConvention.Winapi;
CharSet charset = CharSet.Ansi;
bool preserve_sig = true;
- bool exact_spelling = false;
- bool set_last_err = false;
+ /*bool exact_spelling = false;
+ bool set_last_err = false;*/
string entry_point = null;
for (int i = 0; i < named_args.Count; i++) {
charset = (CharSet) c.GetValue ();
else if (member_name == "EntryPoint")
entry_point = (string) c.GetValue ();
- else if (member_name == "SetLastError")
+ /*else if (member_name == "SetLastError")
set_last_err = (bool) c.GetValue ();
else if (member_name == "ExactSpelling")
- exact_spelling = (bool) c.GetValue ();
+ exact_spelling = (bool) c.GetValue ();*/
else if (member_name == "PreserveSig")
preserve_sig = (bool) c.GetValue ();
} else {
mb.SetImplementationFlags (MethodImplAttributes.PreserveSig);
return mb;
- }
+ }
+
+ public bool IsAssemblyAttribute {
+ get {
+ return ExplicitTarget == "assembly";
+ }
+ }
+
+ public bool IsModuleAttribute {
+ get {
+ return ExplicitTarget == "module";
+ }
+ }
}
- public class AttributeSection {
-
- public readonly string Target;
- public readonly ArrayList Attributes;
+ public class Attributes {
+ public ArrayList Attrs;
+ public Location Location;
- public AttributeSection (string target, ArrayList attrs)
+ public Attributes (Attribute a)
{
- Target = target;
- Attributes = attrs;
+ Attrs = new ArrayList ();
+ Attrs.Add (a);
}
-
- }
-
- public class Attributes {
- public ArrayList AttributeSections;
- public Location Location;
- public Attributes (AttributeSection a, Location loc)
+ public Attributes (ArrayList attrs)
{
- AttributeSections = new ArrayList ();
- AttributeSections.Add (a);
-
+ Attrs = attrs;
}
- public void AddAttribute (AttributeSection a)
+ public void Add (Attribute attr)
{
- if (a != null)
- AttributeSections.Add (a);
+ Attrs.Add (attr);
}
-
- public void AddAttributeSection (AttributeSection a)
+
+ public void Add (ArrayList attrs)
{
- if (a != null && !AttributeSections.Contains (a))
- AttributeSections.Add (a);
+ Attrs.AddRange (attrs);
}
-
- public bool Contains (Type t)
- {
- foreach (AttributeSection attr_section in AttributeSections){
- foreach (Attribute a in attr_section.Attributes){
- if (a.Type == t)
- return true;
- }
- }
- return false;
- }
+
+ public void Emit (EmitContext ec, Attributable ias)
+ {
+ ListDictionary ld = new ListDictionary ();
+
+ foreach (Attribute a in Attrs)
+ a.Emit (ec, ias, ld);
+ }
}
}