2006-08-17 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / mbas / codegen.cs
index 4ad6eadf712522db840ff3cc4774fb28229dbfd0..163ad3c866d9af02cfb5fc20c0d70c34952f0e04 100644 (file)
@@ -14,18 +14,46 @@ using System.Reflection;
 using System.Reflection.Emit;
 using System.Diagnostics.SymbolStore;
 
-namespace Mono.CSharp {
+namespace Mono.MonoBASIC {
 
        /// <summary>
        ///    Code generator class.
        /// </summary>
        public class CodeGen {
                static AppDomain current_domain;
-               public static AssemblyBuilder AssemblyBuilder;
-               public static ModuleBuilder   ModuleBuilder;
+
+               public static AssemblyBuilder AssemblyBuilder {
+                       get { 
+                               return Assembly.Builder;
+                       }                               
+
+                       set {
+                               Assembly.Builder = value;
+                       }                               
+               }
+
+               public static ModuleBuilder ModuleBuilder {
+                       get { 
+                               return Module.Builder;
+                       }                               
+
+                       set {
+                               Module.Builder = value;
+                       }                               
+               }
+
+               public static AssemblyClass Assembly;
+               public static ModuleClass Module;
+               public static ArrayList ArrListVersion = new ArrayList();//keeps the version's 4 numbers
 
                static public ISymbolWriter SymbolWriter;
 
+               static CodeGen ()
+               {
+                       Assembly = new AssemblyClass ();
+                       Module = new ModuleClass ();
+               }
+
                public static string Basename (string name)
                {
                        int pos = name.LastIndexOf ("/");
@@ -103,7 +131,7 @@ namespace Mono.CSharp {
                        // If we got an ISymbolWriter instance, initialize it.
                        //
                        if (SymbolWriter == null) {
-                               Report.Error (
+                               Report.Warning (
                                        -18, "Cannot find any symbol writer");
                                return;
                        }
@@ -124,12 +152,12 @@ namespace Mono.CSharp {
                        case "MonoSymbolWriter":
                                if (!InitMonoSymbolWriter (basename, symbol_output,
                                                           exe_output_file, args))
-                                       Report.Error (
+                                       Report.Warning (
                                                -18, "Cannot initialize the symbol writer");
                                break;
 
                        default:
-                               Report.Error (
+                               Report.Warning (
                                        -18, "Cannot generate debugging information on this platform");
                                break;
                        }
@@ -147,6 +175,12 @@ namespace Mono.CSharp {
                        an = new AssemblyName ();
                        an.Name = TrimExt (Basename (name));
                        current_domain = AppDomain.CurrentDomain;
+                       
+                       if (ArrListVersion.Count < 4)//4 -> Major, Minor,Version, Build
+                       for(int i=ArrListVersion.Count-1;i<4;i++)
+                               ArrListVersion.Add(0);
+                       an.Version = new Version (Convert.ToInt32(ArrListVersion[0]), Convert.ToInt32(ArrListVersion[1]), Convert.ToInt32(ArrListVersion[2]), Convert.ToInt32(ArrListVersion[3]));
+       
                        AssemblyBuilder = current_domain.DefineDynamicAssembly (
                                an, AssemblyBuilderAccess.RunAndSave, Dirname (name));
 
@@ -158,6 +192,7 @@ namespace Mono.CSharp {
                        // If the third argument is true, the ModuleBuilder will dynamically
                        // load the default symbol writer.
                        //
+                       
                        ModuleBuilder = AssemblyBuilder.DefineDynamicModule (
                                Basename (name), Basename (output), want_debugging_support);
 
@@ -203,6 +238,28 @@ namespace Mono.CSharp {
                                SymbolWriter.Close ();
                        }
                }
+
+               public static void AddGlobalAttributes (ArrayList attrs)
+               {
+                       foreach (Attribute attr in attrs) {
+                               if (attr.IsAssemblyAttribute)
+                               {
+                                       Assembly.AddAttribute (attr);
+                               }
+                               else if (attr.IsModuleAttribute)
+                               {
+                                       Module.AddAttribute (attr);
+                               }
+                       }
+               }
+
+               public static void EmitGlobalAttributes ()
+               {
+                       //Assembly.Emit (Tree.Types);
+                       //Module.Emit (Tree.Types);
+                       
+
+               }
        }
 
        /// <summary>
@@ -210,9 +267,11 @@ namespace Mono.CSharp {
        ///   properties bodies, indexer bodies or constructor bodies)
        /// </summary>
        public class EmitContext {
+               
                public DeclSpace DeclSpace;
                public TypeContainer TypeContainer;
                public ILGenerator   ig;
+       
 
                /// <summary>
                ///   This variable tracks the `checked' state of the compilation,
@@ -291,6 +350,16 @@ namespace Mono.CSharp {
                /// </summary>
                public bool HasReturnLabel;
 
+               /// <summary>
+               ///   The location where to exit
+               /// </summary>
+               public Label ExitLabel;
+
+               /// <summary>
+               ///   If we already defined the ExitLabel
+               /// </summary>
+               public bool HasExitLabel;
+
                /// <summary>
                ///   Whether we are in a Finally block
                /// </summary>
@@ -310,6 +379,11 @@ namespace Mono.CSharp {
                ///  Whether we are inside an unsafe block
                /// </summary>
                public bool InUnsafe;
+               
+               /// <summary>
+               ///  Whether we are inside an unsafe block
+               /// </summary>
+               public bool InvokingOwnOverload;                
 
                /// <summary>
                ///   Location for this EmitContext
@@ -332,6 +406,8 @@ namespace Mono.CSharp {
                ///   we relax the rules
                /// </summary>
                public bool InEnumContext;
+               
+               public string BlockName;
 
                protected Stack FlowStack;
                
@@ -339,7 +415,6 @@ namespace Mono.CSharp {
                                    Type return_type, int code_flags, bool is_constructor)
                {
                        this.ig = ig;
-
                        TypeContainer = parent;
                        DeclSpace = ds;
                        CheckState = RootContext.Checked;
@@ -349,6 +424,8 @@ namespace Mono.CSharp {
                        ReturnType = return_type;
                        IsConstructor = is_constructor;
                        CurrentBlock = null;
+                       BlockName = "";
+                       InvokingOwnOverload = false;
                        
                        if (parent != null){
                                // Can only be null for the ResolveType contexts.
@@ -434,7 +511,7 @@ namespace Mono.CSharp {
                // </summary>
                public void KillFlowBranching ()
                {
-                       FlowBranching cfb = (FlowBranching) FlowStack.Pop ();
+                       /*FlowBranching cfb = (FlowBranching)*/ FlowStack.Pop ();
                }
 
                // <summary>
@@ -487,12 +564,22 @@ namespace Mono.CSharp {
                                CurrentBranching.SetParameterAssigned (number);
                }
 
+               // These are two overloaded methods for EmitTopBlock
+               // since in MonoBasic functions we need the Function name
+               // along with its top block, in order to be able to
+               // retrieve the return value when there is no explicit 
+               // 'Return' statement
                public void EmitTopBlock (Block block, InternalParameters ip, Location loc)
                {
-                       bool has_ret = false;
+                       EmitTopBlock (block, "", ip, loc);
+               }
 
-//                     Console.WriteLine ("Emitting: " + loc);
+               public void EmitTopBlock (Block block, string bname, InternalParameters ip, Location loc)
+               {
+                       bool has_ret = false;
 
+                       //Console.WriteLine ("Emitting: '{0}", bname);
+                       BlockName = bname;
                        if (CodeGen.SymbolWriter != null)
                                Mark (loc);
 
@@ -533,26 +620,36 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (ReturnType != null && !has_ret){
-                               //
-                               // FIXME: we need full flow analysis to implement this
-                               // correctly and emit an error instead of a warning.
-                               //
-                               //
-                               Report.Error (161, loc, "Not all code paths return a value");
-                               return;
-                       }
-
                        if (HasReturnLabel)
                                ig.MarkLabel (ReturnLabel);
                        if (return_value != null){
                                ig.Emit (OpCodes.Ldloc, return_value);
                                ig.Emit (OpCodes.Ret);
-                       } else {
-                               if (!InTry){
-                                       if (!has_ret || HasReturnLabel)
-                                               ig.Emit (OpCodes.Ret);
+                               return;
+                       }
+
+                       if (ReturnType != null && !has_ret){
+                               //
+                               // mcs here would report an error (and justly so), but functions without
+                               // an explicit return value are perfectly legal in MonoBasic
+                               //
+                               
+                               VariableInfo vi = block.GetVariableInfo (bname);
+                               if (vi != null) 
+                               {
+                                       ig.Emit (OpCodes.Ldloc, vi.LocalBuilder);
+                                       ig.Emit (OpCodes.Ret);
                                }
+                               else
+                                       Report.Error (-200, "This is not supposed to happen !");
+                               return;
+                       }
+
+                       if (!InTry){
+                               if (!has_ret)
+                                       ig.Emit (OpCodes.Ret);
+                               else if (ReturnType == null)
+                                       ig.Emit (OpCodes.Ret);
                        }
                }
 
@@ -663,4 +760,82 @@ namespace Mono.CSharp {
                        }
                }
        }
+
+       
+       public abstract class CommonAssemblyModulClass: Attributable {
+               protected CommonAssemblyModulClass ():
+                       base (null)
+               {
+               }
+
+               public void AddAttribute (Attribute attr)
+               {
+                       if (OptAttributes == null) {
+                               OptAttributes = new Attributes (attr);
+                       } else {
+                               OptAttributes.Add (attr);
+                       }
+               }
+
+               public virtual void Emit (TypeContainer tc) 
+               {
+                       if (OptAttributes == null)
+                               return;
+                       EmitContext ec = new EmitContext (tc, Location.Null, null, null, 0, false);
+                       
+                       if (OptAttributes != null)
+                               OptAttributes.Emit (ec, this);
+               }
+               
+               
+       }
+
+       public class AssemblyClass: CommonAssemblyModulClass 
+       {
+               public AssemblyBuilder Builder;
+
+               public override AttributeTargets AttributeTargets {
+                       get {
+                               return AttributeTargets.Assembly;
+                       }
+               }
+               
+               public override void Emit (TypeContainer tc)
+               {
+                       base.Emit (tc);
+               }
+
+               public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder customBuilder)
+               {
+                       Builder.SetCustomAttribute (customBuilder);
+               }
+
+       }
+       
+       public class ModuleClass: CommonAssemblyModulClass 
+       {
+               public ModuleBuilder Builder;
+
+               public ModuleClass ()
+               {
+               }
+
+               public override void Emit (TypeContainer tc)
+               {
+                       base.Emit (tc);
+               }
+       
+               public override AttributeTargets AttributeTargets {
+                       get {
+                               return AttributeTargets.Module;
+                       }
+               }
+
+               public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder customBuilder)
+               {
+                       Builder.SetCustomAttribute (customBuilder);
+               }
+       }
 }
+
+