//
// class.cs: Class and Struct handlers
//
// Author: Miguel de Icaza (miguel@gnu.org)
//
// Licensed under the terms of the GNU GPL
//
// (C) 2001 Ximian, Inc (http://www.ximian.com)
//
//
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
using System;
namespace CIR {
public class TypeContainer : DeclSpace {
protected int mod_flags;
// Holds a list of classes and structures
ArrayList types;
// Holds the list of properties
ArrayList properties;
// Holds the list of enumerations
ArrayList enums;
// Holds the list of delegates
ArrayList delegates;
// Holds the list of constructors
ArrayList constructors;
// Holds the list of fields
ArrayList fields;
// Holds a list of fields that have initializers
ArrayList initialized_fields;
// Holds a list of static fields that have initializers
ArrayList initialized_static_fields;
// Holds the list of constants
ArrayList constants;
// Holds the list of
ArrayList interfaces;
// Holds the methods.
ArrayList methods;
// Holds the events
ArrayList events;
// Holds the indexers
ArrayList indexers;
// Holds the operators
ArrayList operators;
// Maps MethodBuilders to Methods
static Hashtable method_builders_to_methods;
//
// Pointers to the default constructor and the default static constructor
//
Constructor default_constructor;
Constructor default_static_constructor;
//
// Whether we have seen a static constructor for this class or not
//
bool have_static_constructor = false;
//
// This is the namespace in which this typecontainer
// was declared. We use this to resolve names.
//
Namespace my_namespace;
//
// This one is computed after we can distinguish interfaces
// from classes from the arraylist `type_bases'
//
string base_class_name;
TypeContainer parent;
ArrayList type_bases;
//
// This behaves like a property ;-)
//
public readonly RootContext RootContext;
// Attributes for this type
protected Attributes attributes;
public TypeContainer (RootContext rc, TypeContainer parent, string name) : base (name)
{
string n;
types = new ArrayList ();
this.parent = parent;
RootContext = rc;
object a = rc.Report;
if (parent == null)
n = "";
else
n = parent.Name;
base_class_name = null;
//Console.WriteLine ("New class " + name + " inside " + n);
}
public AdditionResult AddConstant (Constant constant)
{
AdditionResult res;
string name = constant.Name;
if ((res = IsValid (name)) != AdditionResult.Success)
return res;
if (constants == null)
constants = new ArrayList ();
constants.Add (constant);
DefineName (name, constant);
return AdditionResult.Success;
}
public AdditionResult AddEnum (CIR.Enum e)
{
AdditionResult res;
string name = e.Name;
if ((res = IsValid (name)) != AdditionResult.Success)
return res;
if (enums == null)
enums = new ArrayList ();
enums.Add (e);
DefineName (name, e);
return AdditionResult.Success;
}
public AdditionResult AddClass (Class c)
{
AdditionResult res;
string name = c.Name;
if ((res = IsValid (name)) != AdditionResult.Success)
return res;
DefineName (name, c);
types.Add (c);
return AdditionResult.Success;
}
public AdditionResult AddStruct (Struct s)
{
AdditionResult res;
string name = s.Name;
if ((res = IsValid (name)) != AdditionResult.Success)
return res;
DefineName (name, s);
types.Add (s);
return AdditionResult.Success;
}
public AdditionResult AddDelegate (Delegate d)
{
AdditionResult res;
string name = d.Name;
if ((res = IsValid (name)) != AdditionResult.Success)
return res;
if (delegates == null)
delegates = new ArrayList ();
DefineName (name, d);
delegates.Add (d);
return AdditionResult.Success;
}
public AdditionResult AddMethod (Method method)
{
string name = method.Name;
Object value = defined_names [name];
if (value != null && (!(value is Method)))
return AdditionResult.NameExists;
if (methods == null)
methods = new ArrayList ();
methods.Add (method);
if (value != null)
DefineName (name, method);
return AdditionResult.Success;
}
public AdditionResult AddConstructor (Constructor c)
{
if (c.Name != Basename)
return AdditionResult.NotAConstructor;
if (constructors == null)
constructors = new ArrayList ();
constructors.Add (c);
bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
if (is_static)
have_static_constructor = true;
if (c.IsDefault ()) {
if (is_static)
default_static_constructor = c;
else
default_constructor = c;
}
return AdditionResult.Success;
}
public AdditionResult AddInterface (Interface iface)
{
AdditionResult res;
string name = iface.Name;
if ((res = IsValid (name)) != AdditionResult.Success)
return res;
if (interfaces == null)
interfaces = new ArrayList ();
interfaces.Add (iface);
DefineName (name, iface);
return AdditionResult.Success;
}
public AdditionResult AddField (Field field)
{
AdditionResult res;
string name = field.Name;
if ((res = IsValid (name)) != AdditionResult.Success)
return res;
if (fields == null)
fields = new ArrayList ();
fields.Add (field);
if (field.Initializer != null){
if ((field.ModFlags & Modifiers.STATIC) != 0){
if (initialized_static_fields == null)
initialized_static_fields = new ArrayList ();
initialized_static_fields.Add (field);
//
// We have not seen a static constructor,
// but we will provide static initialization of fields
//
have_static_constructor = true;
} else {
if (initialized_fields == null)
initialized_fields = new ArrayList ();
initialized_fields.Add (field);
}
}
DefineName (name, field);
return AdditionResult.Success;
}
public AdditionResult AddProperty (Property prop)
{
AdditionResult res;
string name = prop.Name;
if ((res = IsValid (name)) != AdditionResult.Success)
return res;
if (properties == null)
properties = new ArrayList ();
properties.Add (prop);
DefineName (name, prop);
return AdditionResult.Success;
}
public AdditionResult AddEvent (Event e)
{
AdditionResult res;
string name = e.Name;
if ((res = IsValid (name)) != AdditionResult.Success)
return res;
if (events == null)
events = new ArrayList ();
events.Add (e);
DefineName (name, e);
return AdditionResult.Success;
}
public AdditionResult AddIndexer (Indexer i)
{
if (indexers == null)
indexers = new ArrayList ();
indexers.Add (i);
return AdditionResult.Success;
}
public AdditionResult AddOperator (Operator op)
{
if (operators == null)
operators = new ArrayList ();
operators.Add (op);
return AdditionResult.Success;
}
public TypeContainer Parent {
get {
return parent;
}
}
public ArrayList Types {
get {
return types;
}
}
public ArrayList Methods {
get {
return methods;
}
}
public ArrayList Constants {
get {
return constants;
}
}
public ArrayList Interfaces {
get {
return interfaces;
}
}
public int ModFlags {
get {
return mod_flags;
}
}
public string Base {
get {
return base_class_name;
}
}
public ArrayList Bases {
get {
return type_bases;
}
set {
type_bases = value;
}
}
public ArrayList Fields {
get {
return fields;
}
}
public ArrayList Constructors {
get {
return constructors;
}
}
public ArrayList Properties {
get {
return properties;
}
}
public ArrayList Events {
get {
return events;
}
}
public ArrayList Enums {
get {
return enums;
}
}
public ArrayList Indexers {
get {
return indexers;
}
}
public ArrayList Operators {
get {
return operators;
}
}
public ArrayList Delegates {
get {
return delegates;
}
}
public Attributes OptAttributes {
get {
return attributes;
}
}
public Namespace Namespace {
get {
return my_namespace;
}
set {
my_namespace = value;
}
}
//
// root_types contains all the types. All TopLevel types
// hence have a parent that points to `root_types', that is
// why there is a non-obvious test down here.
//
public bool IsTopLevel {
get {
if (parent != null){
if (parent.Parent == null)
return true;
}
return false;
}
}
public bool HaveStaticConstructor {
get {
return have_static_constructor;
}
}
public virtual TypeAttributes TypeAttr {
get {
return Modifiers.TypeAttr (mod_flags, this);
}
}
//
// Emits the instance field initializers
//
public bool EmitFieldInitializers (EmitContext ec, bool is_static)
{
ArrayList fields;
ILGenerator ig = ec.ig;
if (is_static)
fields = initialized_static_fields;
else
fields = initialized_fields;
if (fields == null)
return true;
foreach (Field f in fields){
Object init = f.Initializer;
if (init is Expression){
Expression e = (Expression) init;
e = e.Resolve (this);
if (e == null)
return false;
if (!is_static)
ig.Emit (OpCodes.Ldarg_0);
e.Emit (ec);
if (is_static)
ig.Emit (OpCodes.Stsfld, f.FieldBuilder);
else
ig.Emit (OpCodes.Stfld, f.FieldBuilder);
}
}
return true;
}
//
// Defines the default constructors
//
void DefineDefaultConstructor (bool is_static)
{
Constructor c;
int mods = 0;
c = new Constructor (Name, new Parameters (null, null),
new ConstructorBaseInitializer (null, new Location ("", 0, 0)));
AddConstructor (c);
c.Block = new Block (null);
if (is_static)
mods = Modifiers.STATIC;
c.ModFlags = mods;
}
//
// Populates our TypeBuilder with fields and methods
//
public void Populate ()
{
if (Constants != null){
foreach (Constant c in Constants)
c.EmitConstant (RootContext, this);
}
if (Fields != null){
foreach (Field f in Fields)
f.Define (this);
}
if (default_constructor == null)
DefineDefaultConstructor (false);
if (initialized_static_fields != null && default_static_constructor == null)
DefineDefaultConstructor (true);
if (Constructors != null){
foreach (Constructor c in Constructors){
c.Define (this);
if (method_builders_to_methods == null)
method_builders_to_methods = new Hashtable ();
method_builders_to_methods.Add (c.ConstructorBuilder, c);
}
}
if (Methods != null){
foreach (Method m in Methods){
m.Define (this);
if (method_builders_to_methods == null)
method_builders_to_methods = new Hashtable ();
method_builders_to_methods.Add (m.MethodBuilder, m);
}
}
if (Properties != null) {
foreach (Property p in Properties)
p.Define (this);
}
if (Enums != null) {
foreach (Enum e in Enums)
e.Define (this);
}
if (Events != null) {
foreach (Event e in Events)
e.Define (this);
}
if (Indexers != null) {
foreach (Indexer i in Indexers)
i.Define (this);
}
if (Operators != null) {
foreach (Operator o in Operators) {
o.Define (this);
if (method_builders_to_methods == null)
method_builders_to_methods = new Hashtable ();
method_builders_to_methods.Add (o.OperatorMethodBuilder, o.OperatorMethod);
}
}
if (Delegates != null) {
foreach (Delegate d in Delegates)
d.Define (this);
}
}
//
// the `mb' must be a MethodBuilder or a
// ConstructorBuilder, we return the method that
// defines it.
//
static public MethodCore LookupMethodByBuilder (MethodBase mb)
{
return (MethodCore) method_builders_to_methods [mb];
}
//
// Emits the code, this step is performed after all
// the types, enumerations, constructors
//
public void Emit ()
{
if (Constructors != null)
foreach (Constructor c in Constructors)
c.Emit (this);
if (Methods != null)
foreach (Method m in Methods)
m.Emit (this);
if (Operators != null)
foreach (Operator o in Operators)
o.Emit (this);
}
public delegate void ExamineType (TypeContainer container, object cback_data);
void WalkTypesAt (TypeContainer root, ExamineType visit, object cback_data)
{
if (root == null)
return;
foreach (TypeContainer type in root.Types){
visit (type, cback_data);
WalkTypesAt (type, visit, cback_data);
}
}
public void WalkTypes (ExamineType visit, object cback)
{
WalkTypesAt (this, visit, cback);
}
public Type LookupType (string name, bool silent)
{
return RootContext.LookupType (this, name, silent);
}
bool AlwaysAccept (MemberInfo m, object filterCriteria)
{
return true;
}
//
// This method returns the members of this type just like Type.FindMembers would
// Only, we need to use this for types which are _being_ defined because MS'
// implementation can't take care of that.
//
public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
MemberFilter filter, object criteria)
{
ArrayList members = new ArrayList ();
if (filter == null)
filter = new MemberFilter (AlwaysAccept);
if ((mt & MemberTypes.Field) != 0 && Fields != null) {
foreach (Field f in Fields) {
if (filter (f.FieldBuilder, criteria) == true)
members.Add (f.FieldBuilder);
}
}
if ((mt & MemberTypes.Method) != 0) {
if (Methods != null){
foreach (Method m in Methods) {
if (filter (m.MethodBuilder, criteria) == true)
members.Add (m.MethodBuilder);
}
}
if (Operators != null){
foreach (Operator o in Operators) {
if (filter (o.OperatorMethodBuilder, criteria) == true)
members.Add (o.OperatorMethodBuilder);
}
}
}
// FIXME : This ain't right because EventBuilder is not a
// MemberInfo. What do we do ?
if ((mt & MemberTypes.Event) != 0 && Events != null) {
//foreach (Event e in Events) {
// if (filter (e.EventBuilder, criteria) == true)
// mi [i++] = e.EventBuilder;
//}
}
if ((mt & MemberTypes.Property) != 0 && Properties != null) {
foreach (Property p in Properties) {
if (filter (p.PropertyBuilder, criteria) == true)
members.Add (p.PropertyBuilder);
}
}
if ((mt & MemberTypes.NestedType) != 0 && Types != null) {
foreach (TypeContainer t in Types) {
if (filter (t.TypeBuilder, criteria) == true)
members.Add (t.TypeBuilder);
}
}
if ((mt & MemberTypes.Constructor) != 0){
if (Constructors != null){
foreach (Constructor c in Constructors)
if (filter (c.ConstructorBuilder, criteria) == true)
members.Add (c.ConstructorBuilder);
}
}
int count = members.Count;
if (count > 0){
MemberInfo [] mi = new MemberInfo [count];
members.CopyTo (mi);
return mi;
}
return null;
}
}
public class Class : TypeContainer {
//
// Modifiers allowed in a class declaration
//
public const int AllowedModifiers =
Modifiers.NEW |
Modifiers.PUBLIC |
Modifiers.PROTECTED |
Modifiers.INTERNAL |
Modifiers.PRIVATE |
Modifiers.ABSTRACT |
Modifiers.SEALED;
public Class (RootContext rc, TypeContainer parent, string name, int mod, Attributes attrs)
: base (rc, parent, name)
{
int accmods;
if (parent.Parent == null)
accmods = Modifiers.INTERNAL;
else
accmods = Modifiers.PRIVATE;
this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
this.attributes = attrs;
}
//
// FIXME: How do we deal with the user specifying a different
// layout?
//
public override TypeAttributes TypeAttr {
get {
return base.TypeAttr | TypeAttributes.AutoLayout;
}
}
}
public class Struct : TypeContainer {
//
// Modifiers allowed in a struct declaration
//
public const int AllowedModifiers =
Modifiers.NEW |
Modifiers.PUBLIC |
Modifiers.PROTECTED |
Modifiers.INTERNAL |
Modifiers.PRIVATE;
public Struct (RootContext rc, TypeContainer parent, string name, int mod, Attributes attrs)
: base (rc, parent, name)
{
int accmods;
if (parent.Parent == null)
accmods = Modifiers.INTERNAL;
else
accmods = Modifiers.PRIVATE;
this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
this.mod_flags |= Modifiers.SEALED;
this.attributes = attrs;
}
//
// FIXME: Allow the user to specify a different set of attributes
// in some cases (Sealed for example is mandatory for a class,
// but what SequentialLayout can be changed
//
public override TypeAttributes TypeAttr {
get {
return base.TypeAttr |
TypeAttributes.SequentialLayout |
TypeAttributes.Sealed |
TypeAttributes.BeforeFieldInit;
}
}
}
public class MethodCore {
public readonly Parameters Parameters;
public readonly string Name;
public int ModFlags;
Block block;
//
// Parameters, cached for semantic analysis.
//
InternalParameters parameter_info;
public MethodCore (string name, Parameters parameters)
{
Name = name;
Parameters = parameters;
}
//
// Returns the System.Type array for the parameters of this method
//
Type [] parameter_types;
public Type [] ParameterTypes (TypeContainer parent)
{
if (Parameters == null)
return null;
if (parameter_types == null)
parameter_types = Parameters.GetParameterInfo (parent);
return parameter_types;
}
public InternalParameters ParameterInfo
{
get {
return parameter_info;
}
set {
parameter_info = value;
}
}
public Block Block {
get {
return block;
}
set {
block = value;
}
}
public CallingConventions GetCallingConvention (bool is_class)
{
CallingConventions cc = 0;
cc = Parameters.GetCallingConvention ();
if (is_class)
if ((ModFlags & Modifiers.STATIC) == 0)
cc |= CallingConventions.HasThis;
// FIXME: How is `ExplicitThis' used in C#?
return cc;
}
}
public class Method : MethodCore {
public readonly string ReturnType;
public MethodBuilder MethodBuilder;
public readonly Attributes OptAttributes;
//
// Modifiers allowed in a class declaration
//
const int AllowedModifiers =
Modifiers.NEW |
Modifiers.PUBLIC |
Modifiers.PROTECTED |
Modifiers.INTERNAL |
Modifiers.PRIVATE |
Modifiers.STATIC |
Modifiers.VIRTUAL |
Modifiers.SEALED |
Modifiers.OVERRIDE |
Modifiers.ABSTRACT |
Modifiers.EXTERN;
// return_type can be "null" for VOID values.
public Method (string return_type, int mod, string name, Parameters parameters,
Attributes attrs)
: base (name, parameters)
{
ReturnType = return_type;
ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
OptAttributes = attrs;
}
//
// Returns the `System.Type' for the ReturnType of this
// function. Provides a nice cache. (used between semantic analysis
// and actual code generation
//
Type type_return_type;
public Type GetReturnType (TypeContainer parent)
{
if (type_return_type == null)
type_return_type = parent.LookupType (ReturnType, false);
return type_return_type;
}
//
// Creates the type
//
public void Define (TypeContainer parent)
{
Type ret_type = GetReturnType (parent);
Type [] parameters = ParameterTypes (parent);
//
// Create the method
//
MethodBuilder = parent.TypeBuilder.DefineMethod (
Name, Modifiers.MethodAttr (ModFlags),
GetCallingConvention (parent is Class),
ret_type, parameters);
ParameterInfo = new InternalParameters (parameters);
//
// This is used to track the Entry Point,
//
// FIXME: Allow pluggable entry point, check arguments, etc.
//
if (Name == "Main"){
if ((ModFlags & Modifiers.STATIC) != 0){
parent.RootContext.EntryPoint = MethodBuilder;
}
}
//
// Define each type attribute (in/out/ref) and
// the argument names.
//
Parameter [] p = Parameters.FixedParameters;
if (p != null){
int i;
for (i = 0; i < p.Length; i++)
MethodBuilder.DefineParameter (
i + 1, p [i].Attributes, p [i].Name);
if (i != parameters.Length)
Console.WriteLine ("Implement the type definition for params");
}
}
//
// Emits the code
//
public void Emit (TypeContainer parent)
{
ILGenerator ig = MethodBuilder.GetILGenerator ();
EmitContext ec = new EmitContext (parent, ig);
ec.EmitTopBlock (Block);
}
}
public abstract class ConstructorInitializer {
ArrayList argument_list;
ConstructorInfo parent_constructor;
Location location;
public ConstructorInitializer (ArrayList argument_list, Location location)
{
this.argument_list = argument_list;
this.location = location;
}
public ArrayList Arguments {
get {
return argument_list;
}
}
public bool Resolve (TypeContainer tc)
{
Expression parent_constructor_group;
if (argument_list != null){
for (int i = argument_list.Count; i > 0; ){
--i;
Argument a = (Argument) argument_list [i];
if (!a.Resolve (tc))
return false;
}
}
parent_constructor_group = Expression.MemberLookup (
tc,
tc.TypeBuilder.BaseType, ".ctor", false,
MemberTypes.Constructor,
BindingFlags.Public | BindingFlags.Instance);
if (parent_constructor_group == null){
Console.WriteLine ("Could not find a constructor in our parent");
return false;
}
parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (tc,
(MethodGroupExpr) parent_constructor_group, argument_list, location);
if (parent_constructor == null)
return false;
return true;
}
public void Emit (EmitContext ec)
{
ec.ig.Emit (OpCodes.Ldarg_0);
if (argument_list != null)
Invocation.EmitArguments (ec, parent_constructor, argument_list);
ec.ig.Emit (OpCodes.Call, parent_constructor);
}
}
public class ConstructorBaseInitializer : ConstructorInitializer {
public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
{
}
}
public class ConstructorThisInitializer : ConstructorInitializer {
public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
{
}
}
public class Constructor : MethodCore {
public ConstructorBuilder ConstructorBuilder;
public ConstructorInitializer Initializer;
//
// Modifiers allowed for a constructor.
//
const int AllowedModifiers =
Modifiers.PUBLIC |
Modifiers.PROTECTED |
Modifiers.INTERNAL |
Modifiers.STATIC |
Modifiers.PRIVATE;
//
// The spec claims that static is not permitted, but
// my very own code has static constructors.
//
public Constructor (string name, Parameters args, ConstructorInitializer init)
: base (name, args)
{
Initializer = init;
}
//
// Returns true if this is a default constructor
//
public bool IsDefault ()
{
return (Parameters == null ? true : Parameters.Empty) &&
(Initializer is ConstructorBaseInitializer) &&
(Initializer.Arguments == null);
}
//
// Creates the ConstructorBuilder
//
public void Define (TypeContainer parent)
{
MethodAttributes ca = (MethodAttributes.RTSpecialName |
MethodAttributes.SpecialName);
Type [] parameters = ParameterTypes (parent);
if ((ModFlags & Modifiers.STATIC) != 0)
ca |= MethodAttributes.Static;
ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
ca, GetCallingConvention (parent is Class),
parameters);
ParameterInfo = new InternalParameters (parameters);
}
//
// Emits the code
//
public void Emit (TypeContainer parent)
{
if (Initializer != null)
if (!Initializer.Resolve (parent))
return;
ILGenerator ig = ConstructorBuilder.GetILGenerator ();
EmitContext ec = new EmitContext (parent, ig);
if ((ModFlags & Modifiers.STATIC) == 0)
Initializer.Emit (ec);
if ((ModFlags & Modifiers.STATIC) != 0)
parent.EmitFieldInitializers (ec, true);
else
parent.EmitFieldInitializers (ec, false);
ec.EmitTopBlock (Block);
}
}
public class Field {
public readonly string Type;
public readonly Object Initializer;
public readonly string Name;
public readonly int ModFlags;
public readonly Attributes OptAttributes;
public FieldBuilder FieldBuilder;
//
// Modifiers allowed in a class declaration
//
const int AllowedModifiers =
Modifiers.NEW |
Modifiers.PUBLIC |
Modifiers.PROTECTED |
Modifiers.INTERNAL |
Modifiers.PRIVATE |
Modifiers.STATIC |
Modifiers.READONLY;
public Field (string type, int mod, string name, Object expr_or_array_init, Attributes attrs)
{
Type = type;
ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
Name = name;
Initializer = expr_or_array_init;
OptAttributes = attrs;
}
public void Define (TypeContainer parent)
{
Type t = parent.LookupType (Type, false);
if (t == null)
return;
FieldBuilder = parent.TypeBuilder.DefineField (
Name, t, Modifiers.FieldAttr (ModFlags));
}
}
public class Property {
public readonly string Type;
public readonly string Name;
public readonly int ModFlags;
public Block Get, Set;
public PropertyBuilder PropertyBuilder;
public Attributes OptAttributes;
const int AllowedModifiers =
Modifiers.NEW |
Modifiers.PUBLIC |
Modifiers.PROTECTED |
Modifiers.INTERNAL |
Modifiers.PRIVATE |
Modifiers.STATIC |
Modifiers.SEALED |
Modifiers.OVERRIDE |
Modifiers.ABSTRACT |
Modifiers.VIRTUAL;
public Property (string type, string name, int mod_flags, Block get_block, Block set_block, Attributes attrs)
{
Type = type;
Name = name;
ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
Get = get_block;
Set = set_block;
OptAttributes = attrs;
}
public void Define (TypeContainer parent)
{
MethodAttributes method_attr = Modifiers.MethodAttr(ModFlags);
// FIXME - PropertyAttributes.HasDefault ?
PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
PropertyAttributes.SpecialName;
Type tp = parent.LookupType (Type, false);
Type [] prop_type = new Type [1];
prop_type [0] = tp;
MethodBuilder mb;
PropertyBuilder = parent.TypeBuilder.DefineProperty(Name, prop_attr, tp, null);
if (Get != null)
{
mb = parent.TypeBuilder.DefineMethod("get_" + Name, method_attr, tp, null);
PropertyBuilder.SetGetMethod (mb);
}
if (Set != null)
{
mb = parent.TypeBuilder.DefineMethod("set_" + Name, method_attr, null, prop_type);
mb.DefineParameter(1, ParameterAttributes.None, "value");
PropertyBuilder.SetSetMethod (mb);
}
}
}
public class Event {
const int AllowedModifiers =
Modifiers.NEW |
Modifiers.PUBLIC |
Modifiers.PROTECTED |
Modifiers.INTERNAL |
Modifiers.PRIVATE |
Modifiers.STATIC |
Modifiers.VIRTUAL |
Modifiers.SEALED |
Modifiers.OVERRIDE |
Modifiers.ABSTRACT;
public readonly string Type;
public readonly string Name;
public readonly Object Initializer;
public readonly int ModFlags;
public readonly Block Add;
public readonly Block Remove;
public EventBuilder EventBuilder;
public Attributes OptAttributes;
public Event (string type, string name, Object init, int flags, Block add_block, Block rem_block,
Attributes attrs)
{
Type = type;
Name = name;
Initializer = init;
ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
Add = add_block;
Remove = rem_block;
OptAttributes = attrs;
}
public void Define (TypeContainer parent)
{
MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
MethodBuilder mb;
Type t = parent.LookupType (Type, false);
Type [] p_type = new Type [1];
p_type [0] = t;
EventBuilder = parent.TypeBuilder.DefineEvent (Name, e_attr, t);
if (Add != null) {
mb = parent.TypeBuilder.DefineMethod ("add_" + Name, m_attr, null, p_type);
mb.DefineParameter (1, ParameterAttributes.None, "value");
EventBuilder.SetAddOnMethod (mb);
}
if (Remove != null) {
mb = parent.TypeBuilder.DefineMethod ("remove_" + Name, m_attr, null, p_type);
mb.DefineParameter (1, ParameterAttributes.None, "value");
EventBuilder.SetRemoveOnMethod (mb);
}
}
}
public class Indexer {
const int AllowedModifiers =
Modifiers.NEW |
Modifiers.PUBLIC |
Modifiers.PROTECTED |
Modifiers.INTERNAL |
Modifiers.PRIVATE |
Modifiers.VIRTUAL |
Modifiers.SEALED |
Modifiers.OVERRIDE |
Modifiers.ABSTRACT;
public readonly string Type;
public readonly string InterfaceType;
public readonly Parameters FormalParameters;
public readonly int ModFlags;
public readonly Block Get;
public readonly Block Set;
public Attributes OptAttributes;
public MethodBuilder GetMethodBuilder;
public MethodBuilder SetMethodBuilder;
public Indexer (string type, string int_type, int flags, Parameters parms,
Block get_block, Block set_block, Attributes attrs)
{
Type = type;
InterfaceType = int_type;
ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
FormalParameters = parms;
Get = get_block;
Set = set_block;
OptAttributes = attrs;
}
public void Define (TypeContainer parent)
{
MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
Type ret_type = parent.LookupType (Type, false);
Type [] param_types = FormalParameters.GetParameterInfo (parent);
GetMethodBuilder = parent.TypeBuilder.DefineMethod ("get_Item", attr, ret_type, param_types);
SetMethodBuilder = parent.TypeBuilder.DefineMethod ("set_Item", attr, ret_type, param_types);
Parameter [] p = FormalParameters.FixedParameters;
if (p != null) {
int i;
for (i = 0; i < p.Length; ++i) {
GetMethodBuilder.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
SetMethodBuilder.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
}
if (i != param_types.Length)
Console.WriteLine ("Implement type definition for params");
}
}
}
public class Operator {
const int AllowedModifiers =
Modifiers.PUBLIC |
Modifiers.STATIC;
const int RequiredModifiers =
Modifiers.PUBLIC |
Modifiers.STATIC;
public enum OpType {
// Unary operators
Negate,
BitComplement,
Increment,
Decrement,
True,
False,
// Unary and Binary operators
Addition,
Subtraction,
// Binary operators
Multiply,
Division,
Modulus,
BitwiseAnd,
BitwiseOr,
ExclusiveOr,
LeftShift,
RightShift,
Equality,
Inequality,
GreaterThan,
LessThan,
GreaterThanOrEqual,
LessThanOrEqual,
// Implicit and Explicit
Implicit,
Explicit
};
public readonly OpType OperatorType;
public readonly string ReturnType;
public readonly string FirstArgType;
public readonly string FirstArgName;
public readonly string SecondArgType;
public readonly string SecondArgName;
public readonly int ModFlags;
public readonly Block Block;
public Attributes OptAttributes;
public MethodBuilder OperatorMethodBuilder;
public string MethodName;
public Method OperatorMethod;
public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
string arg2type, string arg2name, Block block, Attributes attrs)
{
OperatorType = type;
ReturnType = ret_type;
ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC);
FirstArgType = arg1type;
FirstArgName = arg1name;
SecondArgType = arg2type;
SecondArgName = arg2name;
Block = block;
OptAttributes = attrs;
}
string Prototype (TypeContainer parent)
{
return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
SecondArgType + ")";
}
public void Define (TypeContainer parent)
{
int length = 1;
MethodName = "op_" + OperatorType;
if (SecondArgType != null)
length = 2;
Parameter [] param_list = new Parameter [length];
if ((ModFlags & RequiredModifiers) != RequiredModifiers){
parent.RootContext.Report.Error (
558,
"User defined operators `" +
Prototype (parent) +
"' must be declared static and public");
}
param_list[0] = new Parameter (FirstArgType, FirstArgName,
Parameter.Modifier.NONE, null);
if (SecondArgType != null)
param_list[1] = new Parameter (SecondArgType, SecondArgName,
Parameter.Modifier.NONE, null);
OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
new Parameters (param_list, null), OptAttributes);
OperatorMethod.Define (parent);
OperatorMethodBuilder = OperatorMethod.MethodBuilder;
}
public void Emit (TypeContainer parent)
{
OperatorMethod.Block = Block;
OperatorMethod.Emit (parent);
}
}
}