Simplify the recursive toplevel definition process.
Initial steps to fix the toplevel delegate type reference declarations.
2002-03-30 Miguel de Icaza <miguel@ximian.com>
* expression.cs (Unary): Optimize - - expr into expr.
(Binary): Optimize a + (-b) into a -b.
* codegen.cs (CodeGen): Made all methods static.
2002-03-29 Miguel de Icaza <miguel@ximian.com>
* rootcontext.cs:
* decl.cs: Rename `definition' into `TypeBuilder' and drop the
TypeBuilder property.
* cs-parser.jay: Drop the use of RecordXXX and use RecordDecl
instead.
* tree.cs: Removed the various RecordXXXX, and replaced with a
single RecordDecl. Removed all the accessor methods, and just
left a single access point Type
* enum.cs: Rename DefineEnum to DefineType.
* decl.cs: New abstract method `DefineType' used to unify the
Defines for Enumerations, Interfaces, TypeContainers and
Delegates.
(FindType): Moved LookupInterfaceOrClass here. Moved the
LookupBaseClasses method that used to live in class.cs and
interface.cs here, and renamed to FindType.
* delegate.cs: Implement DefineType. Take advantage of the
refactored pattern for locating the parent builder without taking
the parent_builder argument (which we know does not work if we are
nested, and triggering a toplevel definition).
svn path=/trunk/mcs/; revision=3519
+2002-03-30 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (Unary): Optimize - - expr into expr.
+ (Binary): Optimize a + (-b) into a -b.
+
+ * codegen.cs (CodeGen): Made all methods static.
+
+2002-03-29 Miguel de Icaza <miguel@ximian.com>
+
+ * rootcontext.cs:
+
+ * decl.cs: Rename `definition' into `TypeBuilder' and drop the
+ TypeBuilder property.
+
+ * cs-parser.jay: Drop the use of RecordXXX and use RecordDecl
+ instead.
+
+ * tree.cs: Removed the various RecordXXXX, and replaced with a
+ single RecordDecl. Removed all the accessor methods, and just
+ left a single access point Type
+
+ * enum.cs: Rename DefineEnum to DefineType.
+
+ * decl.cs: New abstract method `DefineType' used to unify the
+ Defines for Enumerations, Interfaces, TypeContainers and
+ Delegates.
+
+ (FindType): Moved LookupInterfaceOrClass here. Moved the
+ LookupBaseClasses method that used to live in class.cs and
+ interface.cs here, and renamed to FindType.
+
+ * delegate.cs: Implement DefineType. Take advantage of the
+ refactored pattern for locating the parent builder without taking
+ the parent_builder argument (which we know does not work if we are
+ nested, and triggering a toplevel definition).
+
2002-03-28 Miguel de Icaza <miguel@ximian.com>
* decl.cs (MemberCore.CheckMethodAgainstBase): Test if the
OPTIMIZATIONS
-------------
-* Make the CodeGen fields static (like SymbolWriter, which gets used a lot)
+* Implement loop inversion for our loops
* Add test case for destructors
It could be static for all we care, and just use it for making
sure that there are no recursive invocations on it.
-* Static-ization
-
- Since AppDomain exists, maybe we can get rid of all the stuff
- that is part of the `compiler instance' and just use globals
- everywhere.
-
-
-* Constructors
-
- Currently it calls the parent constructor before initializing fields.
- It should do it the other way around.
-
* Use of EmitBranchable
Currently I use brfalse/brtrue in the code for statements, instead of
in the stack, so that later a Store can be emitted using that
this pointer (consider Property++ or Indexer++)
-
* Optimizations: variable allocation.
When local variables of a type are required, we should request
}
}
- public static string MakeFQN (string nsn, string name)
- {
- string prefix = (nsn == "" ? "" : nsn + ".");
-
- return prefix + name;
- }
-
- Type LookupInterfaceOrClass (string ns, string name, bool is_class, out bool error)
- {
- TypeContainer parent;
- Type t;
-
- error = false;
- name = MakeFQN (ns, name);
-
- t = TypeManager.LookupType (name);
- if (t != null)
- return t;
-
- if (is_class)
- parent = (Class) RootContext.Tree.Classes [name];
- else
- parent = (Struct) RootContext.Tree.Structs [name];
-
- if (parent == null) {
- Enum en = null;
-
- if (RootContext.Tree.Enums != null)
- en = (Enum) RootContext.Tree.Enums [name];
-
- if (en != null) {
- t = en.DefineEnum ();
-
- if (t != null)
- return t;
- }
- }
-
- if (parent != null){
- t = parent.DefineType ();
- if (t == null){
- Report.Error (146, "Class definition is circular: `"+name+"'");
- error = true;
- return null;
- }
-
- return t;
- }
-
- return null;
- }
-
- //
- // returns the type for an interface or a class, this will recursively
- // try to define the types that it depends on.
- //
- Type GetInterfaceOrClass (string name, bool is_class)
- {
- Type t;
- bool error;
-
- //
- // For the case the type we are looking for is nested within this one
- // or is in any base class
- //
- DeclSpace containing_ds = this;
-
- while (containing_ds != null){
- Type current_type = containing_ds.TypeBuilder;
-
- while (current_type != null) {
- string pre = current_type.FullName;
-
- t = LookupInterfaceOrClass (pre, name, is_class, out error);
- if (error)
- return null;
-
- if (t != null)
- return t;
-
- current_type = current_type.BaseType;
- }
- containing_ds = containing_ds.Parent;
- }
-
- //
- // Attempt to lookup the class on our namespace and all it's implicit parents
- //
- for (string ns = Namespace.Name; ns != null; ns = RootContext.ImplicitParent (ns)) {
-
- t = LookupInterfaceOrClass (ns, name, is_class, out error);
- if (error)
- return null;
-
- if (t != null)
- return t;
- }
-
- //
- // Attempt to do a direct unqualified lookup
- //
- t = LookupInterfaceOrClass ("", name, is_class, out error);
- if (error)
- return null;
-
- if (t != null)
- return t;
-
- //
- // Attempt to lookup the class on any of the `using'
- // namespaces
- //
-
- for (Namespace ns = Namespace; ns != null; ns = ns.Parent){
-
- t = LookupInterfaceOrClass (ns.Name, name, is_class, out error);
- if (error)
- return null;
-
- if (t != null)
- return t;
-
- //
- // Now check the using clause list
- //
- ArrayList using_list = ns.UsingTable;
-
- if (using_list == null)
- continue;
-
- foreach (string n in using_list){
- t = LookupInterfaceOrClass (n, name, is_class, out error);
- if (error)
- return null;
-
- if (t != null)
- return t;
- }
-
- }
-
- Report.Error (246, Location, "Can not find type `"+name+"'");
- return null;
- }
-
/// <summary>
/// This function computes the Base class and also the
/// list of interfaces that the class or struct @c implements.
if (is_class){
string name = (string) bases [0];
- Type first = GetInterfaceOrClass (name, is_class);
+ Type first = FindType (name);
if (first == null){
error = true;
for (i = start, j = 0; i < count; i++, j++){
string name = (string) bases [i];
- Type t = GetInterfaceOrClass (name, is_class);
+ Type t = FindType (name);
if (t == null){
error = true;
//
// Defines the type in the appropriate ModuleBuilder or TypeBuilder.
//
- public TypeBuilder DefineType ()
+ public override TypeBuilder DefineType ()
{
Type parent;
Type [] ifaces;
if (error)
return null;
- if (this is Class && parent != null){
+ if (is_class && parent != null){
if (parent == TypeManager.enum_type ||
(parent == TypeManager.value_type && RootContext.StdLib) ||
parent == TypeManager.delegate_type ||
// if (parent_builder is ModuleBuilder) {
if (IsTopLevel){
- ModuleBuilder builder = RootContext.ModuleBuilder;
+ ModuleBuilder builder = CodeGen.ModuleBuilder;
//
// Structs with no fields need to have a ".size 1"
if (Interfaces != null){
foreach (Interface iface in Interfaces)
- iface.DefineInterface ();
+ iface.DefineType ();
}
if (Types != null) {
if (Delegates != null) {
foreach (Delegate d in Delegates)
- d.DefineDelegate (TypeBuilder);
+ d.DefineType ();
}
if (Enums != null) {
foreach (Enum en in Enums)
- en.DefineEnum ();
+ en.DefineType ();
}
InTransit = false;
{
Report.Error (
17, Location,
- "Program `" + RootContext.CodeGen.FileName +
+ "Program `" + CodeGen.FileName +
"' has more than one entry point defined: `" +
b.DeclaringType.Name + "." + b.Name + "'");
}
if (Name == "Finalize" && type_return_type == TypeManager.void_type)
EmitDestructor (ec);
else {
- ISymbolWriter sw = RootContext.CodeGen.SymbolWriter;
+ ISymbolWriter sw = CodeGen.SymbolWriter;
if ((sw != null) && (!Location.IsNull (Location))) {
MethodToken token = MethodBuilder.GetToken ();
/// Code generator class.
/// </summary>
public class CodeGen {
- AppDomain current_domain;
- AssemblyBuilder assembly_builder;
- ModuleBuilder module_builder;
+ static AppDomain current_domain;
+ static AssemblyBuilder assembly_builder;
+ static ModuleBuilder module_builder;
- public ISymbolWriter SymbolWriter;
+ static public ISymbolWriter SymbolWriter;
public static string Basename (string name)
{
return name;
}
- string TrimExt (string name)
+ static string TrimExt (string name)
{
int pos = name.LastIndexOf (".");
return name.Substring (0, pos);
}
- public string FileName;
+ static public string FileName;
//
// This routine initializes the Mono runtime SymbolWriter.
//
- void InitMonoSymbolWriter (string basename)
+ static void InitMonoSymbolWriter (string basename)
{
string symbol_output = basename + "-debug.s";
//
// Initializes the symbol writer
//
- void InitializeSymbolWriter (string basename)
+ static void InitializeSymbolWriter (string basename)
{
SymbolWriter = module_builder.GetSymWriter ();
break;
}
}
-
- public CodeGen (string name, string output, bool want_debugging_support)
+
+ //
+ // Initializes the code generator variables
+ //
+ static public void Init (string name, string output, bool want_debugging_support)
{
AssemblyName an;
InitializeSymbolWriter (an.Name);
}
- public AssemblyBuilder AssemblyBuilder {
+ static public AssemblyBuilder AssemblyBuilder {
get {
return assembly_builder;
}
}
- public ModuleBuilder ModuleBuilder {
+ static public ModuleBuilder ModuleBuilder {
get {
return module_builder;
}
}
- public void Save (string name)
+ static public void Save (string name)
{
try {
assembly_builder.Save (Basename (name));
}
}
- public void SaveSymbols ()
+ static public void SaveSymbols ()
{
if (SymbolWriter != null) {
// If we have a symbol writer, call its Close() method to write
// Console.WriteLine ("Emitting: " + loc);
- if (RootContext.CodeGen.SymbolWriter != null)
+ if (CodeGen.SymbolWriter != null)
Mark (loc);
if (block != null){
(Attributes) $1, lexer.Location);
current_container = new_struct;
current_container.Namespace = current_namespace;
- RootContext.Tree.RecordStruct (full_struct_name, new_struct);
+ RootContext.Tree.RecordDecl (full_struct_name, new_struct);
}
opt_struct_interfaces
struct_body
}
current_interface = new_interface;
new_interface.Namespace = current_namespace;
- RootContext.Tree.RecordInterface (full_interface_name, new_interface);
+ RootContext.Tree.RecordDecl (full_interface_name, new_interface);
}
opt_interface_base
interface_body opt_semicolon
e.Namespace = current_namespace;
CheckDef (current_container.AddEnum (e), full_name, enum_location);
- RootContext.Tree.RecordEnum (full_name, e);
+ RootContext.Tree.RecordDecl (full_name, e);
}
;
MakeName ((string) $5), (Parameters) $7,
(Attributes) $1, l);
-
+ del.Namespace = current_namespace;
CheckDef (current_container.AddDelegate (del), del.Name, l);
}
| opt_attributes
"System.Void", (int) $2, MakeName ((string) $5), (Parameters) $7,
(Attributes) $1, l);
+ del.Namespace = current_namespace;
CheckDef (current_container.AddDelegate (del), del.Name, l);
}
;
(Attributes) $1, lexer.Location);
current_container = new_class;
current_container.Namespace = current_namespace;
- RootContext.Tree.RecordClass (name, new_class);
+ RootContext.Tree.RecordDecl (name, new_class);
}
opt_class_base
class_body
/// this points to the actual definition that is being
/// created with System.Reflection.Emit
/// </summary>
- TypeBuilder definition;
+ public TypeBuilder TypeBuilder;
/// <summary>
/// This variable tracks whether we have Closed the type
}
}
- public TypeBuilder TypeBuilder {
- get {
- return definition;
- }
-
- set {
- definition = value;
- }
- }
-
public TypeContainer Parent {
get {
return parent;
{
if (!Created){
try {
- definition.CreateType ();
+ TypeBuilder.CreateType ();
} catch {
//
// The try/catch is needed because
}
}
+ /// <remarks>
+ /// Should be overriten by the appropriate declaration space
+ /// <remarks>
+ public abstract TypeBuilder DefineType ();
+
//
// Whether this is an `unsafe context'
//
}
}
+ public static string MakeFQN (string nsn, string name)
+ {
+ string prefix = (nsn == "" ? "" : nsn + ".");
+
+ return prefix + name;
+ }
+
+ Type LookupInterfaceOrClass (string ns, string name, out bool error)
+ {
+ DeclSpace parent;
+ Type t;
+
+ error = false;
+ name = MakeFQN (ns, name);
+
+ t = TypeManager.LookupType (name);
+ if (t != null)
+ return t;
+
+ parent = (DeclSpace) RootContext.Tree.Decls [name];
+ if (parent == null)
+ return null;
+
+ t = parent.DefineType ();
+ if (t == null){
+ Report.Error (146, "Class definition is circular: `"+name+"'");
+ error = true;
+ return null;
+ }
+ return t;
+ }
+
+ /// <summary>
+ /// GetType is used to resolve type names at the DeclSpace level.
+ /// Use this to lookup class/struct bases, interface bases or
+ /// delegate type references
+ /// </summary>
+ ///
+ /// <remarks>
+ /// Contrast this to LookupType which is used inside method bodies to
+ /// lookup types that have already been defined. GetType is used
+ /// during the tree resolution process and potentially define
+ /// recursively the type
+ /// </remarks>
+ public Type FindType (string name)
+ {
+ Type t;
+ bool error;
+
+ //
+ // For the case the type we are looking for is nested within this one
+ // or is in any base class
+ //
+ DeclSpace containing_ds = this;
+
+ while (containing_ds != null){
+ Type current_type = containing_ds.TypeBuilder;
+
+ while (current_type != null) {
+ string pre = current_type.FullName;
+
+ t = LookupInterfaceOrClass (pre, name, out error);
+ if (error)
+ return null;
+
+ if (t != null)
+ return t;
+
+ current_type = current_type.BaseType;
+ }
+ containing_ds = containing_ds.Parent;
+ }
+
+ //
+ // Attempt to lookup the class on our namespace and all it's implicit parents
+ //
+ for (string ns = Namespace.Name; ns != null; ns = RootContext.ImplicitParent (ns)) {
+
+ t = LookupInterfaceOrClass (ns, name, out error);
+ if (error)
+ return null;
+
+ if (t != null)
+ return t;
+ }
+
+ //
+ // Attempt to do a direct unqualified lookup
+ //
+ t = LookupInterfaceOrClass ("", name, out error);
+ if (error)
+ return null;
+
+ if (t != null)
+ return t;
+
+ //
+ // Attempt to lookup the class on any of the `using'
+ // namespaces
+ //
+
+ for (Namespace ns = Namespace; ns != null; ns = ns.Parent){
+
+ t = LookupInterfaceOrClass (ns.Name, name, out error);
+ if (error)
+ return null;
+
+ if (t != null)
+ return t;
+
+ //
+ // Now check the using clause list
+ //
+ ArrayList using_list = ns.UsingTable;
+
+ if (using_list == null)
+ continue;
+
+ foreach (string n in using_list){
+ t = LookupInterfaceOrClass (n, name, out error);
+ if (error)
+ return null;
+
+ if (t != null)
+ return t;
+ }
+
+ }
+
+ Report.Error (246, Location, "Can not find type `"+name+"'");
+ return null;
+ }
}
}
OptAttributes = attrs;\r
}\r
\r
- public void DefineDelegate (object parent_builder)\r
+ public override TypeBuilder DefineType ()\r
{\r
TypeAttributes attr;\r
\r
if (TypeBuilder != null)\r
- return;\r
+ return TypeBuilder;\r
\r
string name = Name.Substring (1 + Name.LastIndexOf ('.'));\r
\r
- if (parent_builder is ModuleBuilder) {\r
- ModuleBuilder builder = (ModuleBuilder) parent_builder;\r
+ if (IsTopLevel) {\r
+ ModuleBuilder builder = CodeGen.ModuleBuilder;\r
attr = TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed;\r
\r
TypeBuilder = builder.DefineType (\r
name, attr, TypeManager.multicast_delegate_type);\r
} else {\r
- // FIXME: We could just use TypeBuilder here.\r
- TypeBuilder builder = (System.Reflection.Emit.TypeBuilder) parent_builder;\r
+ TypeBuilder builder = Parent.TypeBuilder;\r
attr = TypeAttributes.NestedPublic | TypeAttributes.Class |\r
TypeAttributes.Sealed;\r
\r
}\r
\r
TypeManager.AddDelegateType (Name, TypeBuilder, this);\r
+\r
+ return TypeBuilder;\r
}\r
\r
public override bool Define (TypeContainer parent)\r
\r
\r
ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);\r
- \r
- // Here the various methods like Invoke, BeginInvoke etc are defined\r
\r
//\r
- // Invoke method\r
+ // Here the various methods like Invoke, BeginInvoke etc are defined\r
//\r
- param_types = Parameters.GetParameterInfo (parent);\r
+ // First, call the `out of band' special method for\r
+ // defining recursively any types we need:\r
+ Parameters.ComputeAndDefineParameterTypes (this);\r
+ \r
+ param_types = Parameters.GetParameterInfo (this);\r
if (param_types == null)\r
return false;\r
\r
+\r
+ //\r
+ // Invoke method\r
+ //\r
+ \r
// Check accessibility\r
foreach (Type partype in param_types)\r
if (!TypeContainer.AsAccessible (partype, ModFlags))\r
return false;\r
\r
- ret_type = RootContext.LookupType (parent, ReturnType, false, Location);\r
+ ret_type = FindType (ReturnType);\r
if (ret_type == null)\r
return false;\r
\r
output_file = first_source + target_ext;
}
- RootContext.CodeGen = new CodeGen (output_file, output_file,
- want_debugging_support);
+ CodeGen.Init (output_file, output_file, want_debugging_support);
- TypeManager.AddModule (RootContext.CodeGen.ModuleBuilder);
+ TypeManager.AddModule (CodeGen.ModuleBuilder);
//
// Before emitting, we need to get the core
return;
}
- RootContext.CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);
+ CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);
}
//
//
if (resources != null){
foreach (string file in resources)
- RootContext.CodeGen.AssemblyBuilder.AddResourceFile (file, file);
+ CodeGen.AssemblyBuilder.AddResourceFile (file, file);
}
- RootContext.CodeGen.Save (output_file);
+ CodeGen.Save (output_file);
if (timestamps)
ShowTime ("Saved output");
if (want_debugging_support) {
- RootContext.CodeGen.SaveSymbols ();
+ CodeGen.SaveSymbols ();
if (timestamps)
ShowTime ("Saved symbols");
}
return AdditionResult.Success;
}
- public Type DefineEnum ()
+ public override TypeBuilder DefineType ()
{
if (TypeBuilder != null)
return TypeBuilder;
}
if (IsTopLevel) {
- ModuleBuilder builder = RootContext.ModuleBuilder;
+ ModuleBuilder builder = CodeGen.ModuleBuilder;
if ((ModFlags & Modifiers.PUBLIC) != 0)
attr |= TypeAttributes.Public;
Indirection, AddressOf, TOP
}
- Operator oper;
- Expression expr;
+ public Operator Oper;
+ public Expression Expr;
Location loc;
public Unary (Operator op, Expression expr, Location loc)
{
- this.oper = op;
- this.expr = expr;
+ this.Oper = op;
+ this.Expr = expr;
this.loc = loc;
}
- public Expression Expr {
- get {
- return expr;
- }
-
- set {
- expr = value;
- }
- }
-
- public Operator Oper {
- get {
- return oper;
- }
-
- set {
- oper = value;
- }
- }
-
/// <summary>
/// Returns a stringified representation of the Operator
/// </summary>
void Error23 (Type t)
{
Report.Error (
- 23, loc, "Operator " + OperName (oper) +
+ 23, loc, "Operator " + OperName (Oper) +
" cannot be applied to operand of type `" +
TypeManager.CSharpName (t) + "'");
}
e = new IntConstant (-((ShortConstant) expr).Value);
else if (expr is UShortConstant)
e = new IntConstant (-((UShortConstant) expr).Value);
-
return e;
}
{
Type expr_type = e.Type;
- switch (oper){
+ switch (Oper){
case Operator.UnaryPlus:
return e;
Expression ResolveOperator (EmitContext ec)
{
- Type expr_type = expr.Type;
+ Type expr_type = Expr.Type;
//
// Step 1: Perform Operator Overload location
Expression mg;
string op_name;
- op_name = oper_names [(int) oper];
+ op_name = oper_names [(int) Oper];
mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
if (mg != null) {
Expression e = StaticCallExpr.MakeSimpleCall (
- ec, (MethodGroupExpr) mg, expr, loc);
+ ec, (MethodGroupExpr) mg, Expr, loc);
if (e == null){
Error23 (expr_type);
//
// Step 2: Default operations on CLI native types.
//
- if (expr is Constant)
- return Reduce (ec, expr);
+ if (Expr is Constant)
+ return Reduce (ec, Expr);
- if (oper == Operator.LogicalNot){
+ if (Oper == Operator.LogicalNot){
if (expr_type != TypeManager.bool_type) {
- Error23 (expr.Type);
+ Error23 (Expr.Type);
return null;
}
return this;
}
- if (oper == Operator.OnesComplement) {
+ if (Oper == Operator.OnesComplement) {
if (!((expr_type == TypeManager.int32_type) ||
(expr_type == TypeManager.uint32_type) ||
(expr_type == TypeManager.int64_type) ||
(expr_type == TypeManager.uint64_type) ||
(expr_type.IsSubclassOf (TypeManager.enum_type)))){
- Error23 (expr.Type);
+ Error23 (Expr.Type);
return null;
}
type = expr_type;
return this;
}
- if (oper == Operator.UnaryPlus) {
+ if (Oper == Operator.UnaryPlus) {
//
// A plus in front of something is just a no-op, so return the child.
//
- return expr;
+ return Expr;
}
//
// double operator- (double d)
// decimal operator- (decimal d)
//
- if (oper == Operator.UnaryNegation){
+ if (Oper == Operator.UnaryNegation){
Expression e = null;
+ //
+ // transform - - expr into expr
+ //
+ if (Expr is Unary){
+ Unary unary = (Unary) Expr;
+
+ if (unary.Oper == Operator.UnaryNegation)
+ return unary.Expr;
+ }
+
//
// perform numeric promotions to int,
// long, double.
// bt wrote as a decimal interger literal
//
type = TypeManager.int64_type;
- expr = ConvertImplicit (ec, expr, type, loc);
+ Expr = ConvertImplicit (ec, Expr, type, loc);
return this;
}
return this;
}
- e = ConvertImplicit (ec, expr, TypeManager.int32_type, loc);
+ e = ConvertImplicit (ec, Expr, TypeManager.int32_type, loc);
if (e != null){
- expr = e;
+ Expr = e;
type = e.Type;
return this;
}
- e = ConvertImplicit (ec, expr, TypeManager.int64_type, loc);
+ e = ConvertImplicit (ec, Expr, TypeManager.int64_type, loc);
if (e != null){
- expr = e;
+ Expr = e;
type = e.Type;
return this;
}
- e = ConvertImplicit (ec, expr, TypeManager.double_type, loc);
+ e = ConvertImplicit (ec, Expr, TypeManager.double_type, loc);
if (e != null){
- expr = e;
+ Expr = e;
type = e.Type;
return this;
}
return null;
}
- if (oper == Operator.AddressOf){
- if (expr.eclass != ExprClass.Variable){
+ if (Oper == Operator.AddressOf){
+ if (Expr.eclass != ExprClass.Variable){
Error (211, loc, "Cannot take the address of non-variables");
return null;
}
return null;
}
- if (!TypeManager.VerifyUnManaged (expr.Type, loc)){
+ if (!TypeManager.VerifyUnManaged (Expr.Type, loc)){
return null;
}
// are not known by Type.GetType, so we have to try then to use
// ModuleBuilder.GetType.
//
- string ptr_type_name = expr.Type.FullName + "*";
+ string ptr_type_name = Expr.Type.FullName + "*";
type = Type.GetType (ptr_type_name);
if (type == null)
- type = RootContext.ModuleBuilder.GetType (ptr_type_name);
+ type = CodeGen.ModuleBuilder.GetType (ptr_type_name);
return this;
}
- if (oper == Operator.Indirection){
+ if (Oper == Operator.Indirection){
if (!ec.InUnsafe){
UnsafeError (loc);
return null;
// We create an Indirection expression, because
// it can implement the IMemoryLocation.
//
- return new Indirection (expr);
+ return new Indirection (Expr);
}
- Error (187, loc, "No such operator '" + OperName (oper) + "' defined for type '" +
+ Error (187, loc, "No such operator '" + OperName (Oper) + "' defined for type '" +
TypeManager.CSharpName (expr_type) + "'");
return null;
}
public override Expression DoResolve (EmitContext ec)
{
- expr = expr.Resolve (ec);
+ Expr = Expr.Resolve (ec);
- if (expr == null)
+ if (Expr == null)
return null;
eclass = ExprClass.Value;
public override void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
- Type expr_type = expr.Type;
+ Type expr_type = Expr.Type;
- switch (oper) {
+ switch (Oper) {
case Operator.UnaryPlus:
throw new Exception ("This should be caught by Resolve");
case Operator.UnaryNegation:
- expr.Emit (ec);
+ Expr.Emit (ec);
ig.Emit (OpCodes.Neg);
break;
case Operator.LogicalNot:
- expr.Emit (ec);
+ Expr.Emit (ec);
ig.Emit (OpCodes.Ldc_I4_0);
ig.Emit (OpCodes.Ceq);
break;
case Operator.OnesComplement:
- expr.Emit (ec);
+ Expr.Emit (ec);
ig.Emit (OpCodes.Not);
break;
case Operator.AddressOf:
- ((IMemoryLocation)expr).AddressOf (ec, AddressOp.LoadStore);
+ ((IMemoryLocation)Expr).AddressOf (ec, AddressOp.LoadStore);
break;
default:
throw new Exception ("This should not happen: Operator = "
- + oper.ToString ());
+ + Oper.ToString ());
}
}
/// </summary>
public void EmitLogicalNot (EmitContext ec)
{
- if (oper != Operator.LogicalNot)
+ if (Oper != Operator.LogicalNot)
throw new Exception ("EmitLogicalNot can only be called with !expr");
- expr.Emit (ec);
+ Expr.Emit (ec);
}
public override string ToString ()
{
- return "Unary (" + oper + ", " + expr + ")";
+ return "Unary (" + Oper + ", " + Expr + ")";
}
}
return this;
}
+
+ //
+ // Transform a + ( - b) into a - b
+ //
+ if (right is Unary){
+ Unary right_unary = (Unary) right;
+
+ if (right_unary.Oper == Unary.Operator.UnaryNegation){
+ oper = Operator.Subtraction;
+ right = right_unary.Expr;
+ }
+ }
}
if (oper == Operator.Addition || oper == Operator.Subtraction) {
} else {
- ModuleBuilder mb = RootContext.ModuleBuilder;
+ ModuleBuilder mb = CodeGen.ModuleBuilder;
ArrayList args = new ArrayList ();
if (Arguments != null){
if (dims != 1){
Type [] args;
ModuleBuilder mb = null;
- mb = RootContext.ModuleBuilder;
+ mb = CodeGen.ModuleBuilder;
args = new Type [dims + 1];
int j;
MethodInfo FetchGetMethod ()
{
- ModuleBuilder mb = RootContext.ModuleBuilder;
+ ModuleBuilder mb = CodeGen.ModuleBuilder;
int arg_count = ea.Arguments.Count;
Type [] args = new Type [arg_count];
MethodInfo get;
MethodInfo FetchAddressMethod ()
{
- ModuleBuilder mb = RootContext.ModuleBuilder;
+ ModuleBuilder mb = CodeGen.ModuleBuilder;
int arg_count = ea.Arguments.Count;
Type [] args = new Type [arg_count];
MethodInfo address;
if (rank == 1)
EmitStoreOpcode (ig, t);
else {
- ModuleBuilder mb = RootContext.ModuleBuilder;
+ ModuleBuilder mb = CodeGen.ModuleBuilder;
int arg_count = ea.Arguments.Count;
Type [] args = new Type [arg_count + 1];
MethodInfo set;
type = Type.GetType (array_ptr_type_name);
if (type == null){
- ModuleBuilder mb = RootContext.ModuleBuilder;
+ ModuleBuilder mb = CodeGen.ModuleBuilder;
type = mb.GetType (array_ptr_type_name);
}
string ptr_name = otype.FullName + "*";
type = Type.GetType (ptr_name);
if (type == null){
- ModuleBuilder mb = RootContext.ModuleBuilder;
+ ModuleBuilder mb = CodeGen.ModuleBuilder;
type = mb.GetType (ptr_name);
}
return true;
}
- //
- // Returns the Type that represents the interface whose name
- // is `name'.
- //
-
- Type LookupInterfaceByName (string ns, string name, out bool error)
- {
- Interface parent;
- Type t;
-
- error = false;
- name = TypeContainer.MakeFQN (ns, name);
- t = TypeManager.LookupType (name);
-
- if (t != null) {
- if (t.IsInterface)
- return t;
-
- string cause;
-
- if (t.IsValueType)
- cause = "is a struct";
- else if (t.IsClass)
- cause = "is a class";
- else
- cause = "Should not happen.";
-
- error = true;
- Report.Error (527, Location, "`"+name+"' " + cause +
- ", need an interface instead");
-
- return null;
- }
-
- Tree tree = RootContext.Tree;
- parent = (Interface) tree.Interfaces [name];
- if (parent == null)
- return null;
-
- t = parent.DefineInterface ();
- if (t == null){
- Report.Error (529,
- "Inherited interface `"+name+"' is circular");
- error = true;
- return null;
- }
-
- return t;
- }
-
Type GetInterfaceTypeByName (string name)
{
- //
- // For the case the type we are looking for is nested within this one
- // or is in any base class
- //
- DeclSpace containing_ds = this;
- bool error = false;
- Type t;
-
- while (containing_ds != null){
- Type current_type = containing_ds.TypeBuilder;
-
- while (current_type != null) {
- string pre = current_type.FullName;
-
- t = LookupInterfaceByName (pre, name, out error);
- if (error)
- return null;
-
- if (t != null)
- return t;
-
- current_type = current_type.BaseType;
- }
- containing_ds = containing_ds.Parent;
- }
+ Type t = FindType (name);
- //
- // Attempt to lookup the class on our namespace and all it's implicit parents
- //
- for (string ns = Namespace.Name; ns != null; ns = RootContext.ImplicitParent (ns)){
- t = LookupInterfaceByName (ns, name, out error);
- if (error)
- return null;
- if (t != null)
- return t;
- }
-
- //
- // Attempt to do a direct unqualified lookup
- //
- t = LookupInterfaceByName ("", name, out error);
- if (error)
+ if (t == null)
return null;
- if (t != null)
+ if (t.IsInterface)
return t;
-
- //
- // Attempt to lookup the class on any of the `using'
- // namespaces
- //
-
- for (Namespace ns = Namespace; ns != null; ns = ns.Parent){
- t = LookupInterfaceByName (ns.Name, name, out error);
- if (error)
- return null;
-
- if (t != null)
- return t;
-
- //
- // Now check the using clause list
- //
- ArrayList using_list = ns.UsingTable;
- if (using_list == null)
- continue;
-
- foreach (string n in using_list){
- t = LookupInterfaceByName (n, name, out error);
- if (error)
- return null;
-
- if (t != null)
- return t;
- }
- }
-
- Report.Error (246, Location, "Can not find type `"+name+"'");
+ string cause;
+
+ if (t.IsValueType)
+ cause = "is a struct";
+ else if (t.IsClass)
+ cause = "is a class";
+ else
+ cause = "Should not happen.";
+
+ Report.Error (527, Location, "`"+name+"' " + cause +
+ ", need an interface instead");
+
return null;
}
foreach (string name in Bases){
Type t;
-
+
t = GetInterfaceTypeByName (name);
if (t == null){
error = true;
// <summary>
// Defines the Interface in the appropriate ModuleBuilder or TypeBuilder
// </summary>
+ //
// TODO:
// Rework the way we recurse, because for recursive
// definitions of interfaces (A:B and B:A) we report the
// error twice, rather than once.
- public TypeBuilder DefineInterface ()
+ public override TypeBuilder DefineType ()
{
Type [] ifaces;
bool error;
return null;
if (IsTopLevel) {
- ModuleBuilder builder = RootContext.ModuleBuilder;
+ ModuleBuilder builder = CodeGen.ModuleBuilder;
TypeBuilder = builder.DefineType (
Name,
// If we don't have a symbol writer, this property is always null.
public ISymbolDocumentWriter SymbolDocument {
get {
- ISymbolWriter sw = RootContext.CodeGen.SymbolWriter;
+ ISymbolWriter sw = CodeGen.SymbolWriter;
ISymbolDocumentWriter doc;
if (token < 0)
echo --target exe -o mcs2.exe $(COMPILER_SOURCES) > response
dum: cs-parser.cs
- ./mcs --fatal --target exe -o mcs2.exe $(COMPILER_SOURCES)
+ $(TIME) ./mcs --fatal --target exe -o mcs2.exe $(COMPILER_SOURCES)
mcs2.exe: mcs.exe
- ./mcs $(XFLAGS) --target exe -o mcs2.exe $(COMPILER_SOURCES)
+ $(TIME) ./mcs $(XFLAGS) --target exe -o mcs2.exe $(COMPILER_SOURCES)
mcs3.exe: mcs2.exe
- ./mcs2 --target exe -o mcs3.exe $(COMPILER_SOURCES)
+ $(TIME) ./mcs2 --target exe -o mcs3.exe $(COMPILER_SOURCES)
mm:
mint $(MINTFLAGS) ./mcs.exe $(MCSFLAGS) --target exe -o mcs4.exe $(COMPILER_SOURCES)
OptAttributes = attrs;
}
+ // <summary>
+ // Resolve is used in method definitions
+ // </summary>
public bool Resolve (DeclSpace ds, Location l)
{
ParameterType = RootContext.LookupType (ds, TypeName, false, l);
return ParameterType != null;
}
+ // <summary>
+ // ResolveAndDefine is used by delegate declarations, because
+ // they happen during the initial tree resolution process
+ // </summary>
+ public bool ResolveAndDefine (DeclSpace ds)
+ {
+ ParameterType = ds.FindType (TypeName);
+ return ParameterType != null;
+ }
+
public Type ExternalType (DeclSpace ds, Location l)
{
if ((ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0){
return true;
}
+
+ //
+ // This variant is used by Delegates, because they need to
+ // resolve/define names, instead of the plain LookupType
+ //
+ public bool ComputeAndDefineParameterTypes (DeclSpace ds)
+ {
+ int extra = (ArrayParameter != null) ? 1 : 0;
+ int i = 0;
+ int pc;
+
+ if (FixedParameters == null)
+ pc = extra;
+ else
+ pc = extra + FixedParameters.Length;
+
+ types = new Type [pc];
+
+ if (!VerifyArgs ()){
+ FixedParameters = null;
+ return false;
+ }
+
+ if (FixedParameters != null){
+ foreach (Parameter p in FixedParameters){
+ Type t = null;
+
+ if (p.ResolveAndDefine (ds))
+ t = p.ExternalType (ds, loc);
+
+ types [i] = t;
+ i++;
+ }
+ }
+
+ if (extra > 0){
+ if (ArrayParameter.ResolveAndDefine (ds))
+ types [i] = ArrayParameter.ExternalType (ds, loc);
+ }
+
+ return true;
+ }
/// <summary>
/// Returns the argument types as an array
//
static Tree tree;
- //
- // The System.Reflection.Emit CodeGenerator
- //
- static CodeGen cg;
-
static public bool Optimize;
- //
- // The module builder pointer.
- //
- static ModuleBuilder mb;
-
//
// The list of global attributes (those that target the assembly)
//
static public string MainClass;
- static public CodeGen CodeGen {
- get {
- return cg;
- }
-
- set {
- //
- // Temporary hack, we should probably
- // intialize `cg' rather than depending on
- // external initialization of it.
- //
- cg = value;
- mb = cg.ModuleBuilder;
- }
- }
-
public static void RegisterOrder (Interface iface)
{
interface_resolve_order.Add (iface);
ArrayList ifaces = root.Interfaces;
if (ifaces != null){
foreach (Interface i in ifaces)
- i.DefineInterface ();
+ i.DefineType ();
}
foreach (TypeContainer tc in root.Types)
if (root.Delegates != null)
foreach (Delegate d in root.Delegates)
- d.DefineDelegate (mb);
+ d.DefineType ();
if (root.Enums != null)
foreach (Enum e in root.Enums)
- e.DefineEnum ();
+ e.DefineType ();
}
return;
}
- ((TypeContainer) o).DefineType ();
+ ((DeclSpace) o).DefineType ();
}
//
return;
}
- ((TypeContainer) o).DefineType ();
+ ((DeclSpace) o).DefineType ();
}
//
return;
}
- ((Interface) o).DefineInterface ();
+ ((DeclSpace) o).DefineType ();
}
//
return;
}
- ((Delegate) o).DefineDelegate (mb);
+ ((DeclSpace) o).DefineType ();
}
Type current_type = containing_ds.TypeBuilder;
while (current_type != null) {
+ //
+ // nested class
+ //
t = TypeManager.LookupType (current_type.FullName + "+" + name);
if (t != null)
return t;
if (global_attributes != null){
EmitContext ec = new EmitContext (
tree.Types, Mono.CSharp.Location.Null, null, null, 0, false);
- AssemblyBuilder ab = cg.AssemblyBuilder;
+ AssemblyBuilder ab = CodeGen.AssemblyBuilder;
Attribute.ApplyAttributes (ec, ab, ab, global_attributes,
global_attributes.Location);
}
CustomAttributeBuilder cb = new CustomAttributeBuilder (ci, new object [0]);
- mb.SetCustomAttribute (cb);
+ CodeGen.ModuleBuilder.SetCustomAttribute (cb);
}
}
- static public ModuleBuilder ModuleBuilder {
- get {
- return mb;
- }
- }
-
//
// Public Field, used to track which method is the public entry
// point.
int size = data.Length;
if (impl_details_class == null)
- impl_details_class = mb.DefineType (
+ impl_details_class = CodeGen.ModuleBuilder.DefineType (
"<PrivateImplementationDetails>", TypeAttributes.NotPublic);
fb = impl_details_class.DefineInitializedData (
return null;
}
- if (RootContext.CodeGen.SymbolWriter != null)
+ if (CodeGen.SymbolWriter != null)
ec.Mark (loc);
bool invert = false;
vi.VariableType = t;
vi.LocalBuilder = ig.DeclareLocal (t);
- if (RootContext.CodeGen.SymbolWriter != null)
+ if (CodeGen.SymbolWriter != null)
vi.LocalBuilder.SetLocalSymInfo (name);
if (constants == null)
ec.CurrentBlock = this;
- if (RootContext.CodeGen.SymbolWriter != null) {
+ if (CodeGen.SymbolWriter != null) {
ec.Mark (StartLocation);
foreach (Statement s in Statements) {
for (int i = 0; i < rank; i++)
args [i] = TypeManager.int32_type;
- ModuleBuilder mb = RootContext.ModuleBuilder;
+ ModuleBuilder mb = CodeGen.ModuleBuilder;
get = mb.GetArrayMethod (
array_type, "Get",
CallingConventions.HasThis| CallingConventions.Standard,
public class Tree {
TypeContainer root_types;
- // <summary>
- // Keeps track of the interfaces defined in the source code
- // </summary>
- Hashtable ifaces;
-
- // <summary>
- // Keeps track of the structs defined in the source code
- // </summary>
- Hashtable structs;
-
- // <summary>
- // Keeps track of the classes defined in the source code
- // </summary>
- Hashtable classes;
-
// <summary>
// Keeps track of namespaces defined in the source code
// </summary>
Hashtable namespaces;
// <summary>
- // Keeps track of enums defined
+ // Keeps track of all the types definied (classes, structs, ifaces, enums)
// </summary>
- Hashtable enums;
+ Hashtable decls;
public Tree ()
{
root_types = new TypeContainer (null, "", new Location (-1));
+
+ decls = new Hashtable ();
+ namespaces = new Hashtable ();
}
- void RecordDecl (Hashtable decl, string name, DeclSpace ds)
+ public void RecordDecl (string name, DeclSpace ds)
{
- if (decl.Contains (name)){
+ if (decls.Contains (name)){
Report.Error (
101, ds.Location,
"There is already a definition for `" + name + "'");
- DeclSpace other = (DeclSpace) decl [name];
+ DeclSpace other = (DeclSpace) decls [name];
Report.Error (0,
other.Location, "(Location of symbol related to previous error)");
return;
}
- decl.Add (name, ds);
+ decls.Add (name, ds);
}
- public void RecordInterface (string name, Interface iface)
- {
- if (ifaces == null)
- ifaces = new Hashtable ();
-
- RecordDecl (ifaces, name, iface);
- }
-
- public void RecordStruct (string name, Struct s)
- {
- if (structs == null)
- structs = new Hashtable ();
-
- RecordDecl (structs, name, s);
- }
-
- public void RecordClass (string name, Class c)
- {
- if (classes == null)
- classes = new Hashtable ();
-
- RecordDecl (classes, name, c);
- }
-
- public void RecordEnum (string name, Enum e)
- {
- if (enums == null)
- enums = new Hashtable ();
-
- RecordDecl (enums, name, e);
- }
-
public Namespace RecordNamespace (Namespace parent, string file, string name)
{
- if (namespaces == null)
- namespaces = new Hashtable ();
-
Namespace ns = new Namespace (parent, name);
if (namespaces.Contains (file)){
return ns;
}
-
- public TypeContainer Types {
- get {
- return root_types;
- }
- }
-
- public Hashtable Interfaces {
- get {
- return ifaces;
- }
- }
- public Hashtable Classes {
- get {
- return classes;
- }
- }
+ //
+ // FIXME: Why are we using Types?
+ //
+ public TypeContainer Types {
+ get {
+ return root_types;
+ }
+ }
- public Hashtable Structs {
+ public Hashtable Decls {
get {
- return structs;
+ return decls;
}
}
return namespaces;
}
}
-
- public Hashtable Enums {
- get {
- return enums;
- }
- }
}
}