using System;
using System.Collections.Generic;
-using System.Reflection.Emit;
+using System.IO;
namespace Mono.CSharp
{
+ public enum LookupMode
+ {
+ Normal = 0,
+ Probing = 1,
+ IgnoreAccessibility = 2
+ }
+
//
// Implemented by elements which can act as independent contexts
// during resolve phase. Used mostly for lookups.
//
- public interface IMemberContext
+ public interface IMemberContext : IModuleContext
{
//
// A scope type context, it can be inflated for generic types
// A member definition of the context. For partial types definition use
// CurrentTypeDefinition.PartialContainer otherwise the context is local
//
+ // TODO: Obsolete it in this context, dynamic context cannot guarantee sensible value
+ //
MemberCore CurrentMemberDefinition { get; }
bool IsObsolete { get; }
bool IsUnsafe { get; }
bool IsStatic { get; }
- bool HasUnresolvedConstraints { get; }
string GetSignatureForError ();
- ExtensionMethodGroupExpr LookupExtensionMethod (TypeSpec extensionType, string name, int arity, Location loc);
- FullNamedExpression LookupNamespaceOrType (string name, int arity, Location loc, bool ignore_cs0104);
+ ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity);
+ FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc);
FullNamedExpression LookupNamespaceAlias (string name);
+ }
- CompilerContext Compiler { get; }
+ public interface IModuleContext
+ {
+ ModuleContainer Module { get; }
}
//
{
FlowBranching current_flow_branching;
- public TypeInferenceContext ReturnTypeInference;
-
- TypeSpec return_type;
-
- /// <summary>
- /// The location where return has to jump to return the
- /// value
- /// </summary>
- public Label ReturnLabel; // TODO: It's emit dependant
+ readonly TypeSpec return_type;
- /// <summary>
- /// If we already defined the ReturnLabel
- /// </summary>
- public bool HasReturnLabel;
+ public int FlowOffset;
public BlockContext (IMemberContext mc, ExplicitBlock block, TypeSpec returnType)
: base (mc)
CurrentBlock = block;
}
+ public BlockContext (ResolveContext rc, ExplicitBlock block, TypeSpec returnType)
+ : this (rc.MemberContext, block, returnType)
+ {
+ if (rc.IsUnsafe)
+ flags |= ResolveContext.Options.UnsafeScope;
+
+ if (rc.HasSet (ResolveContext.Options.CheckedScope))
+ flags |= ResolveContext.Options.CheckedScope;
+ }
+
public override FlowBranching CurrentBranching {
get { return current_flow_branching; }
}
+ public TypeSpec ReturnType {
+ get { return return_type; }
+ }
+
// <summary>
// Starts a new code branching. This inherits the state of all local
// variables and parameters from the current branching.
return branching;
}
- public FlowBranchingIterator StartFlowBranching (Iterator iterator)
+ public FlowBranchingIterator StartFlowBranching (Iterator iterator, FlowBranching parent)
{
- FlowBranchingIterator branching = new FlowBranchingIterator (CurrentBranching, iterator);
+ FlowBranchingIterator branching = new FlowBranchingIterator (parent, iterator);
current_flow_branching = branching;
return branching;
}
- public FlowBranchingToplevel StartFlowBranching (ToplevelBlock stmt, FlowBranching parent)
+ public FlowBranchingAsync StartFlowBranching (AsyncInitializer asyncBody, FlowBranching parent)
+ {
+ var branching = new FlowBranchingAsync (parent, asyncBody);
+ current_flow_branching = branching;
+ return branching;
+ }
+
+ public FlowBranchingToplevel StartFlowBranching (ParametersBlock stmt, FlowBranching parent)
{
FlowBranchingToplevel branching = new FlowBranchingToplevel (parent, stmt);
current_flow_branching = branching;
current_flow_branching = current_flow_branching.Parent;
}
- //
- // This method is used during the Resolution phase to flag the
- // need to define the ReturnLabel
- //
+#if !STATIC
public void NeedReturnLabel ()
{
- if (!HasReturnLabel)
- HasReturnLabel = true;
- }
-
- public TypeSpec ReturnType {
- get { return return_type; }
}
+#endif
}
//
ConstructorScope = 1 << 11,
+ UsingInitializerScope = 1 << 12,
+
+ LockScope = 1 << 13,
+
/// <summary>
/// Whether control flow analysis is enabled
/// </summary>
}
}
- Options flags;
+ protected Options flags;
//
// Whether we are inside an anonymous method.
public Block CurrentBlock;
- public IMemberContext MemberContext;
+ public readonly IMemberContext MemberContext;
/// <summary>
/// If this is non-null, points to the current switch statement
//
// The default setting comes from the command line option
//
- if (RootContext.Checked)
+ if (mc.Module.Compiler.Settings.Checked)
flags |= Options.CheckedScope;
//
flags |= options;
}
- public CompilerContext Compiler {
- get { return MemberContext.Compiler; }
+ #region Properties
+
+ public BuiltinTypes BuiltinTypes {
+ get {
+ return MemberContext.Module.Compiler.BuiltinTypes;
+ }
+ }
+
+ public virtual ExplicitBlock ConstructorBlock {
+ get {
+ return CurrentBlock.Explicit;
+ }
}
public virtual FlowBranching CurrentBranching {
get { return (flags & Options.DoFlowAnalysis) != 0; }
}
- public bool HasUnresolvedConstraints {
- get { return false; }
+ public bool IsInProbingMode {
+ get {
+ return (flags & Options.ProbingMode) != 0;
+ }
}
- public bool IsInProbingMode {
- get { return (flags & Options.ProbingMode) != 0; }
+ public bool IsObsolete {
+ get {
+ // Disables obsolete checks when probing is on
+ return MemberContext.IsObsolete;
+ }
+ }
+
+ public bool IsStatic {
+ get {
+ return MemberContext.IsStatic;
+ }
+ }
+
+ public bool IsUnsafe {
+ get {
+ return HasSet (Options.UnsafeScope) || MemberContext.IsUnsafe;
+ }
+ }
+
+ public bool IsRuntimeBinder {
+ get {
+ return Module.Compiler.IsRuntimeBinder;
+ }
}
public bool IsVariableCapturingRequired {
}
}
+ public ModuleContainer Module {
+ get {
+ return MemberContext.Module;
+ }
+ }
+
public bool OmitStructFlowAnalysis {
get { return (flags & Options.OmitStructFlowAnalysis) != 0; }
}
- // TODO: Merge with CompilerGeneratedThis
- public Expression GetThis (Location loc)
- {
- This my_this;
- if (CurrentBlock != null)
- my_this = new This (CurrentBlock, loc);
- else
- my_this = new This (loc);
-
- if (!my_this.ResolveBase (this))
- my_this = null;
-
- return my_this;
+ public Report Report {
+ get {
+ return Module.Compiler.Report;
+ }
}
- public bool MustCaptureVariable (LocalInfo local)
+ #endregion
+
+ public bool MustCaptureVariable (INamedBlockVariable local)
{
if (CurrentAnonymousMethod == null)
return false;
if (CurrentAnonymousMethod.IsIterator)
return true;
- return local.Block.Toplevel != CurrentBlock.Toplevel;
+ return local.Block.ParametersBlock != CurrentBlock.ParametersBlock.Original;
}
public bool HasSet (Options options)
return (this.flags & options) != 0;
}
- public Report Report {
- get {
- return Compiler.Report;
- }
- }
// Temporarily set all the given flags to the given value. Should be used in an 'using' statement
public FlagsHandle Set (Options options)
return MemberContext.GetSignatureForError ();
}
- public bool IsObsolete {
- get {
- // Disables obsolete checks when probing is on
- return IsInProbingMode || MemberContext.IsObsolete;
- }
- }
-
- public bool IsStatic {
- get { return MemberContext.IsStatic; }
- }
-
- public bool IsUnsafe {
- get { return HasSet (Options.UnsafeScope) || MemberContext.IsUnsafe; }
- }
-
- public ExtensionMethodGroupExpr LookupExtensionMethod (TypeSpec extensionType, string name, int arity, Location loc)
+ public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
{
- return MemberContext.LookupExtensionMethod (extensionType, name, arity, loc);
+ return MemberContext.LookupExtensionMethod (extensionType, name, arity);
}
- public FullNamedExpression LookupNamespaceOrType (string name, int arity, Location loc, bool ignore_cs0104)
+ public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
{
- return MemberContext.LookupNamespaceOrType (name, arity, loc, ignore_cs0104);
+ return MemberContext.LookupNamespaceOrType (name, arity, mode, loc);
}
public FullNamedExpression LookupNamespaceAlias (string name)
public class CloneContext
{
Dictionary<Block, Block> block_map = new Dictionary<Block, Block> ();
- Dictionary<LocalInfo, LocalInfo> variable_map;
public void AddBlockMap (Block from, Block to)
{
- if (block_map.ContainsKey (from))
- return;
- block_map[from] = to;
+ block_map.Add (from, to);
}
public Block LookupBlock (Block from)
Block result;
if (!block_map.TryGetValue (from, out result)) {
result = (Block) from.Clone (this);
- block_map [from] = result;
}
return result;
return mapped_to;
}
-
- public void AddVariableMap (LocalInfo from, LocalInfo to)
- {
- if (variable_map == null)
- variable_map = new Dictionary<LocalInfo, LocalInfo> ();
- else if (variable_map.ContainsKey (from))
- return;
-
- variable_map[from] = to;
- }
-
- public LocalInfo LookupVariable (LocalInfo from)
- {
- try {
- return variable_map[from];
- } catch (KeyNotFoundException) {
- throw new Exception ("LookupVariable: looking up a variable that has not been registered yet");
- }
- }
}
//
//
public class CompilerContext
{
+ static readonly TimeReporter DisabledTimeReporter = new TimeReporter (false);
+
readonly Report report;
+ readonly BuiltinTypes builtin_types;
+ readonly CompilerSettings settings;
+
+ Dictionary<string, SourceFile> all_source_files;
- public CompilerContext (Report report)
+ public CompilerContext (CompilerSettings settings, Report report)
{
+ this.settings = settings;
this.report = report;
+ this.builtin_types = new BuiltinTypes ();
+ this.TimeReporter = DisabledTimeReporter;
}
- public bool IsRuntimeBinder { get; set; }
+ #region Properties
+
+ public BuiltinTypes BuiltinTypes {
+ get {
+ return builtin_types;
+ }
+ }
+
+ // Used for special handling of runtime dynamic context mostly
+ // by error reporting but also by member accessibility checks
+ public bool IsRuntimeBinder {
+ get; set;
+ }
public Report Report {
- get { return report; }
+ get {
+ return report;
+ }
}
- //public PredefinedAttributes PredefinedAttributes {
- // get { throw new NotImplementedException (); }
- //}
+ public CompilerSettings Settings {
+ get {
+ return settings;
+ }
+ }
+
+ public List<CompilationSourceFile> SourceFiles {
+ get {
+ return settings.SourceFiles;
+ }
+ }
+
+ internal TimeReporter TimeReporter {
+ get; set;
+ }
+
+ #endregion
+
+ //
+ // This is used when we encounter a #line preprocessing directive during parsing
+ // to register additional source file names
+ //
+ public SourceFile LookupFile (CompilationSourceFile comp_unit, string name)
+ {
+ if (all_source_files == null) {
+ all_source_files = new Dictionary<string, SourceFile> ();
+ foreach (var source in SourceFiles)
+ all_source_files[source.FullPathName] = source;
+ }
+
+ string path;
+ if (!Path.IsPathRooted (name)) {
+ string root = Path.GetDirectoryName (comp_unit.FullPathName);
+ path = Path.Combine (root, name);
+ } else
+ path = name;
+
+ SourceFile retval;
+ if (all_source_files.TryGetValue (path, out retval))
+ return retval;
+
+ retval = Location.AddFile (name, path);
+ all_source_files.Add (path, retval);
+ return retval;
+ }
}
//
/// </summary>
CheckedScope = 1 << 0,
- /// <summary>
- /// The constant check state is always set to `true' and cant be changed
- /// from the command line. The source code can change this setting with
- /// the `checked' and `unchecked' statements and expressions.
- /// </summary>
- ConstantCheckState = 1 << 1,
-
- AllCheckStateFlags = CheckedScope | ConstantCheckState,
-
OmitDebugInfo = 1 << 2,
- ConstructorScope = 1 << 3
+ ConstructorScope = 1 << 3,
+
+ AsyncBody = 1 << 4
}
// utility helper for CheckExpr, UnCheckExpr, Checked and Unchecked statements
}
}
- Options flags;
+ protected Options flags;
public bool HasSet (Options options)
{