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 ("/");
// If we got an ISymbolWriter instance, initialize it.
//
if (SymbolWriter == null) {
- Report.Error (
+ Report.Warning (
-18, "Cannot find any symbol writer");
return;
}
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;
}
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));
// 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);
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>
/// 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,
/// </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>
/// 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
/// we relax the rules
/// </summary>
public bool InEnumContext;
+
+ public string BlockName;
protected Stack FlowStack;
Type return_type, int code_flags, bool is_constructor)
{
this.ig = ig;
-
TypeContainer = parent;
DeclSpace = ds;
CheckState = RootContext.Checked;
ReturnType = return_type;
IsConstructor = is_constructor;
CurrentBlock = null;
+ BlockName = "";
+ InvokingOwnOverload = false;
if (parent != null){
// Can only be null for the ResolveType contexts.
// </summary>
public void KillFlowBranching ()
{
- FlowBranching cfb = (FlowBranching) FlowStack.Pop ();
+ /*FlowBranching cfb = (FlowBranching)*/ FlowStack.Pop ();
}
// <summary>
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);
}
}
- 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);
}
}
}
}
}
+
+
+ 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);
+ }
+ }
}
+
+