return null;
}
- //
- // C# 3.0 introduced contextual keywords (var) which behaves like a type if type with
- // same name exists or as a keyword when no type was found
- //
- public virtual TypeExpr ResolveAsContextualType (IMemberContext rc, bool silent)
- {
- return ResolveAsTypeTerminal (rc, silent);
- }
-
//
// This is used to resolve the expression as a type, a null
// value will be returned if the expression is not a type
type.GetSignatureForError (), target.GetSignatureForError ());
}
- public virtual void Error_VariableIsUsedBeforeItIsDeclared (Report Report, string name)
- {
- Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", name);
- }
-
public void Error_TypeArgumentsCannotBeUsed (Report report, Location loc, MemberSpec member, int arity)
{
// Better message for possible generic expressions
ec.Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer");
}
+ protected void Error_VoidPointerOperation (ResolveContext rc)
+ {
+ rc.Report.Error (242, loc, "The operation in question is undefined on void pointers");
+ }
+
public ResolveFlags ExprClassToResolveFlags {
get {
switch (eclass) {
throw;
ec.Report.Error (584, loc, "Internal compiler error: {0}", ex.Message);
- return EmptyExpression.Null;
+ return EmptyExpression.Null; // TODO: Add location
}
}
return r.ResolveMember<MethodSpec> (rc, ref args);
}
+ [Flags]
+ public enum MemberLookupRestrictions
+ {
+ None = 0,
+ InvocableOnly = 1,
+ ExactArity = 1 << 2,
+ ReadAccess = 1 << 3
+ }
+
//
// Lookup type `queried_type' for code in class `container_type' with a qualifier of
// `qualifier_type' or null to lookup members in the current class.
//
- public static Expression MemberLookup (ResolveContext rc, TypeSpec currentType, TypeSpec queried_type, string name, int arity, bool invocableOnly, Location loc)
+ public static Expression MemberLookup (ResolveContext rc, TypeSpec currentType, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc)
{
var members = MemberCache.FindMembers (queried_type, name, false);
if (members == null)
if ((member.Modifiers & Modifiers.OVERRIDE) != 0 && member.Kind != MemberKind.Event)
continue;
- if (arity > 0 && member.Arity != arity)
+ if ((arity > 0 || (restrictions & MemberLookupRestrictions.ExactArity) != 0) && member.Arity != arity)
continue;
if (rc != null && !member.IsAccessible (currentType))
continue;
- if (invocableOnly) {
+ if ((restrictions & MemberLookupRestrictions.InvocableOnly) != 0) {
if (member is MethodSpec)
return new MethodGroupExpr (members, queried_type, loc);
Arguments arguments = new Arguments (1);
arguments.Add (new Argument (e));
- var res = new OverloadResolver (methods, OverloadResolver.Restrictions.NoBaseMembers, loc);
+ var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc);
var oper = res.ResolveOperator (ec, ref arguments);
if (oper == null)
this.loc = orig_expr.Location;
}
+ #region Properties
+
+ public Expression OriginalExpression {
+ get {
+ return orig_expr;
+ }
+ }
+
+ #endregion
+
//
// Creates fully resolved expression switcher
//
return Name;
}
- public abstract Expression LookupNameExpression (ResolveContext rc, bool readMode, bool invocableOnly);
+ public abstract Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restriction);
}
/// <summary>
}
if (Arity == 0 && Name == "dynamic" && RootContext.Version > LanguageVersion.V_3) {
- if (!PredefinedAttributes.Get.Dynamic.IsDefined) {
+ if (!ec.Compiler.PredefinedAttributes.Dynamic.IsDefined) {
ec.Compiler.Report.Error (1980, Location,
"Dynamic keyword requires `{0}' to be defined. Are you missing System.Core.dll assembly reference?",
- PredefinedAttributes.Get.Dynamic.GetSignatureForError ());
+ ec.Compiler.PredefinedAttributes.Dynamic.GetSignatureForError ());
}
return new DynamicTypeExpr (loc);
return null;
}
- public override Expression LookupNameExpression (ResolveContext rc, bool readMode, bool invocableOnly)
+ public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions)
{
int lookup_arity = Arity;
bool errorMode = false;
Expression e;
Block current_block = rc.CurrentBlock;
+ INamedBlockVariable variable = null;
+ bool variable_found = false;
while (true) {
//
// Stage 1: binding to local variables or parameters
//
+ // LAMESPEC: It should take invocableOnly into account but that would break csc compatibility
+ //
if (current_block != null && lookup_arity == 0) {
- LocalInfo vi = current_block.GetLocalInfo (Name);
- if (vi != null) {
- // TODO: pass vi in to speed things up
- e = new LocalVariableReference (rc.CurrentBlock, Name, loc);
- } else {
- e = current_block.Toplevel.GetParameterReference (Name, loc);
- }
-
- if (e != null) {
- if (Arity > 0)
- Error_TypeArgumentsCannotBeUsed (rc.Report, "variable", Name, loc);
-
- return e;
- }
-
- if (!errorMode)
- current_block.CheckInvariantMeaningInBlock (Name, this, loc);
+ if (current_block.ParametersBlock.TopBlock.GetLocalName (Name, current_block.Original, ref variable)) {
+ if (!variable.IsDeclared) {
+ // We found local name in accessible block but it's not
+ // initialized yet, maybe the user wanted to bind to something else
+ errorMode = true;
+ variable_found = true;
+ } else {
+ e = variable.CreateReferenceExpression (rc, loc);
+ if (e != null) {
+ if (Arity > 0)
+ Error_TypeArgumentsCannotBeUsed (rc.Report, "variable", Name, loc);
-/*
- //if (errorMode) {
- IKnownVariable ikv = current_block.Explicit.GetKnownVariable (Name);
- if (ikv != null) {
- LocalInfo li = ikv as LocalInfo;
- // Supress CS0219 warning
- if (li != null)
- li.Used = true;
-
- Error_VariableIsUsedBeforeItIsDeclared (rc.Report, Name);
- return null;
+ return e;
+ }
}
- //}
-*/
+ }
}
//
TypeSpec member_type = rc.CurrentType;
TypeSpec current_type = member_type;
for (; member_type != null; member_type = member_type.DeclaringType) {
- var me = MemberLookup (errorMode ? null : rc, current_type, member_type, Name, lookup_arity, invocableOnly, loc) as MemberExpr;
+ var me = MemberLookup (errorMode ? null : rc, current_type, member_type, Name, lookup_arity, restrictions, loc) as MemberExpr;
if (me == null)
continue;
if (errorMode) {
- if (me is MethodGroupExpr) {
+ if (variable != null) {
+ if (me is FieldExpr || me is ConstantExpr || me is EventExpr || me is PropertyExpr) {
+ rc.Report.Error (844, loc,
+ "A local variable `{0}' cannot be used before it is declared. Consider renaming the local variable when it hides the member `{1}'",
+ Name, me.GetSignatureForError ());
+ } else {
+ break;
+ }
+ } else if (me is MethodGroupExpr) {
// Leave it to overload resolution to report correct error
} else {
// TODO: rc.Report.SymbolRelatedToPreviousError ()
ErrorIsInaccesible (rc, me.GetSignatureForError (), loc);
}
} else {
+ if (variable != null && (restrictions & MemberLookupRestrictions.InvocableOnly) == 0) {
+ rc.Report.SymbolRelatedToPreviousError (variable.Location, Name);
+ rc.Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", Name);
+ }
+
//
// MemberLookup does not check accessors availability, this is actually needed for properties only
//
if (pe != null) {
// Break as there is no other overload available anyway
- if (readMode) {
+ if ((restrictions & MemberLookupRestrictions.ReadAccess) != 0) {
if (!pe.PropertyInfo.HasGet || !pe.PropertyInfo.Get.IsAccessible (current_type))
break;
//
// Stage 3: Lookup nested types, namespaces and type parameters in the context
//
- if (!invocableOnly) {
+ if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0 && !variable_found) {
e = ResolveAsTypeStep (rc, lookup_arity == 0 || !errorMode);
if (e != null)
return e;
}
if (errorMode) {
- rc.Report.Error (103, loc, "The name `{0}' does not exist in the current context", Name);
+ if (variable_found) {
+ rc.Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", Name);
+ } else {
+ rc.Report.Error (103, loc, "The name `{0}' does not exist in the current context", Name);
+ }
+
return null;
}
}
lookup_arity = 0;
- invocableOnly = false;
+ restrictions &= ~MemberLookupRestrictions.InvocableOnly;
errorMode = true;
}
}
-
+
Expression SimpleNameResolve (ResolveContext ec, Expression right_side, bool intermediate)
{
- Expression e = LookupNameExpression (ec, right_side == null, false);
+ Expression e = LookupNameExpression (ec, right_side == null ? MemberLookupRestrictions.ReadAccess : MemberLookupRestrictions.None);
if (e == null)
return null;
- if (right_side != null)
+ if (right_side != null) {
+ if (e is TypeExpr) {
+ e.Error_UnexpectedKind (ec, ResolveFlags.VariableOrValue, loc);
+ return null;
+ }
+
e = e.ResolveLValue (ec, right_side);
- else
+ } else {
e = e.Resolve (ec);
+ }
//if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
return e;
ResolveInstanceExpression (ec);
if (InstanceExpression != null)
CheckProtectedMemberAccess (ec, best_candidate);
-
- if (best_candidate.IsGeneric) {
- ConstraintChecker.CheckAll (ec.MemberContext, best_candidate.GetGenericMethodDefinition (), best_candidate.TypeArguments,
- best_candidate.Constraints, loc);
- }
}
best_candidate = CandidateToBaseOverride (ec, best_candidate);
DelegateInvoke = 1,
ProbingOnly = 1 << 1,
CovariantDelegate = 1 << 2,
- NoBaseMembers = 1 << 3
+ NoBaseMembers = 1 << 3,
+ BaseMembersIncluded = 1 << 4
}
public interface IBaseMembersProvider
AParametersCollection pd = ((IParametersMember) candidate).Parameters;
int param_count = pd.Count;
int optional_count = 0;
+ int score;
if (arg_count != param_count) {
for (int i = 0; i < pd.Count; ++i) {
return int.MaxValue - 10000 + args_gap;
}
- // Initialize expanded form of a method with 1 params parameter
- params_expanded_form = param_count == 1 && pd.HasParams;
-
// Resize to fit optional arguments
if (optional_count != 0) {
- Arguments resized;
if (arguments == null) {
- resized = new Arguments (optional_count);
+ arguments = new Arguments (optional_count);
} else {
- resized = new Arguments (param_count);
+ // Have to create a new container, so the next run can do same
+ var resized = new Arguments (param_count);
resized.AddRange (arguments);
+ arguments = resized;
}
for (int i = arg_count; i < param_count; ++i)
- resized.Add (null);
- arguments = resized;
+ arguments.Add (null);
}
}
int index = pd.GetParameterIndexByName (na.Name);
// Named parameter not found or already reordered
- if (index <= i)
+ if (index == i || index < 0)
break;
- // When using parameters which should not be available to the user
- if (index >= param_count)
- break;
+ Argument temp;
+ if (index >= param_count) {
+ // When using parameters which should not be available to the user
+ if ((pd.FixedParameters[index].ModFlags & Parameter.Modifier.PARAMS) == 0)
+ break;
+
+ arguments.Add (null);
+ ++arg_count;
+ temp = null;
+ } else {
+ temp = arguments[index];
+
+ // The slot has been taken by positional argument
+ if (temp != null && !(temp is NamedArgument))
+ break;
+ }
if (!arg_moved) {
arguments.MarkReorderedArgument (na);
arg_moved = true;
}
- Argument temp = arguments[index];
arguments[index] = arguments[i];
arguments[i] = temp;
//
var ms = candidate as MethodSpec;
if (ms != null && ms.IsGeneric) {
+ // Setup constraint checker for probing only
+ ConstraintChecker cc = new ConstraintChecker (null);
+
if (type_arguments != null) {
var g_args_count = ms.Arity;
if (g_args_count != type_arguments.Count)
prev_recorder = ec.Report.SetPrinter (lambda_conv_msgs);
}
- int score = TypeManager.InferTypeArguments (ec, arguments, ref ms);
+ var ti = new TypeInference (arguments);
+ TypeSpec[] i_args = ti.InferMethodArguments (ec, ms);
lambda_conv_msgs.EndSession ();
- if (score != 0)
- return score - 20000;
+ if (i_args == null)
+ return ti.InferenceScore - 20000;
- candidate = ms;
- pd = ms.Parameters;
+ if (i_args.Length != 0) {
+ candidate = ms = ms.MakeGenericMethod (i_args);
+ pd = ms.Parameters;
+ }
+
+ cc.IgnoreInferredDynamic = true;
}
+
+ //
+ // Type arguments constraints have to match for the method to be applicable
+ //
+ if (!cc.CheckAll (ms.GetGenericMethodDefinition (), ms.TypeArguments, ms.Constraints, loc))
+ return int.MaxValue - 25000;
+
} else {
if (type_arguments != null)
return int.MaxValue - 15000;
if (!pd.FixedParameters[i].HasDefaultValue)
throw new InternalErrorException ();
- Expression e = pd.FixedParameters[i].DefaultValue as Constant;
- if (e == null || e.Type.IsGenericOrParentIsGeneric)
- e = new DefaultValueExpression (new TypeExpression (pd.Types[i], loc), loc).Resolve (ec);
+ //
+ // Get the default value expression, we can use the same expression
+ // if the type matches
+ //
+ Expression e = pd.FixedParameters[i].DefaultValue;
+ if (!(e is Constant) || e.Type.IsGenericOrParentIsGeneric) {
+ //
+ // LAMESPEC: No idea what the exact rules are for System.Reflection.Missing.Value instead of null
+ //
+ if (e == EmptyExpression.MissingValue && pd.Types[i] == TypeManager.object_type) {
+ e = new MemberAccess (new MemberAccess (new MemberAccess (
+ new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Reflection", loc), "Missing", loc), "Value", loc);
+ } else {
+ e = new DefaultValueExpression (new TypeExpression (pd.Types[i], loc), loc);
+ }
+
+ e = e.Resolve (ec);
+ }
arguments[i] = new Argument (e, Argument.AType.Default);
continue;
}
if (p_mod != Parameter.Modifier.PARAMS) {
- p_mod = pd.FixedParameters[i].ModFlags & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
+ p_mod = pd.FixedParameters[i].ModFlags;
pt = pd.Types[i];
- } else {
+ } else if (!params_expanded_form) {
params_expanded_form = true;
+ pt = ((ElementTypeSpec) pt).Element;
+ i -= 2;
+ continue;
}
- Parameter.Modifier a_mod = a.Modifier & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
- int score = 1;
+ score = 1;
if (!params_expanded_form)
- score = IsArgumentCompatible (ec, a_mod, a, p_mod & ~Parameter.Modifier.PARAMS, pt);
+ score = IsArgumentCompatible (ec, a, p_mod & ~Parameter.Modifier.PARAMS, pt);
//
// It can be applicable in expanded form (when not doing exact match like for delegates)
//
if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0 && (restrictions & Restrictions.CovariantDelegate) == 0) {
- score = IsArgumentCompatible (ec, a_mod, a, 0, TypeManager.GetElementType (pt));
+ if (!params_expanded_form)
+ pt = ((ElementTypeSpec) pt).Element;
+
+ score = IsArgumentCompatible (ec, a, Parameter.Modifier.NONE, pt);
if (score == 0)
params_expanded_form = true;
}
}
}
- if (arg_count != pd.Count)
+ //
+ // When params parameter has notargument, will be provided later if the method is the best candidate
+ //
+ if (arg_count + 1 == pd.Count && (pd.FixedParameters [arg_count].ModFlags & Parameter.Modifier.PARAMS) != 0)
params_expanded_form = true;
return 0;
}
- int IsArgumentCompatible (ResolveContext ec, Parameter.Modifier arg_mod, Argument argument, Parameter.Modifier param_mod, TypeSpec parameter)
+ int IsArgumentCompatible (ResolveContext ec, Argument argument, Parameter.Modifier param_mod, TypeSpec parameter)
{
//
// Types have to be identical when ref or out modifer
// is used and argument is not of dynamic type
//
- if ((arg_mod | param_mod) != 0) {
+ if ((argument.Modifier | param_mod) != 0) {
//
// Defer to dynamic binder
//
}
}
- if (arg_mod != param_mod)
+ if (argument.Modifier != param_mod)
return 1;
return 0;
best_candidate_args = candidate_args;
best_candidate_params = params_expanded_form;
} else if (candidate_rate == 0) {
+ //
+ // The member look is done per type for most operations but sometimes
+ // it's not possible like for binary operators overload because they
+ // are unioned between 2 sides
+ //
+ if ((restrictions & Restrictions.BaseMembersIncluded) != 0) {
+ if (TypeSpec.IsBaseClass (best_candidate.DeclaringType, member.DeclaringType, true))
+ continue;
+ }
+
// Is new candidate better
if (BetterFunction (rc, candidate_args, member, params_expanded_form, best_candidate, best_candidate_params)) {
best_candidate = member;
}
var ms = best_candidate as MethodSpec;
- if (ms != null && ms.IsGeneric && ta_count == 0) {
- if (custom_errors != null && custom_errors.TypeInferenceFailed (rc, best_candidate))
- return;
+ if (ms != null && ms.IsGeneric) {
+ bool constr_ok = true;
+ if (ms.TypeArguments != null)
+ constr_ok = new ConstraintChecker (rc.MemberContext).CheckAll (ms.GetGenericMethodDefinition (), ms.TypeArguments, ms.Constraints, loc);
+
+ if (ta_count == 0) {
+ if (custom_errors != null && custom_errors.TypeInferenceFailed (rc, best_candidate))
+ return;
+
+ if (constr_ok) {
+ rc.Report.Error (411, loc,
+ "The type arguments for method `{0}' cannot be inferred from the usage. Try specifying the type arguments explicitly",
+ ms.GetGenericMethodDefinition ().GetSignatureForError ());
+ }
- rc.Report.Error (411, loc,
- "The type arguments for method `{0}' cannot be inferred from the usage. Try specifying the type arguments explicitly",
- ms.GetGenericMethodDefinition ().GetSignatureForError ());
- return;
+ return;
+ }
}
VerifyArguments (rc, ref args, best_candidate, params_expanded);
public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
{
- prepared = prepare_for_load;
+ prepared = prepare_for_load && !(source is DynamicExpressionStatement);
if (IsInstance)
EmitInstance (ec, prepared);
base.EmitSideEffect (ec);
}
- public override void Error_VariableIsUsedBeforeItIsDeclared (Report r, string name)
- {
- r.Error (844, loc,
- "A local variable `{0}' cannot be used before it is declared. Consider renaming the local variable when it hides the field `{1}'",
- name, GetSignatureForError ());
- }
-
public void AddressOf (EmitContext ec, AddressOp mode)
{
if ((mode & AddressOp.Store) != 0)
public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
{
- Expression my_source = source;
+ Arguments args;
- if (prepare_for_load) {
+ if (prepare_for_load && !(source is DynamicExpressionStatement)) {
+ args = new Arguments (0);
prepared = true;
source.Emit (ec);
temp.Store (ec);
}
}
- } else if (leave_copy) {
- source.Emit (ec);
- temp = new LocalTemporary (this.Type);
- temp.Store (ec);
- my_source = temp;
+ } else {
+ args = new Arguments (1);
+
+ if (leave_copy) {
+ source.Emit (ec);
+ temp = new LocalTemporary (this.Type);
+ temp.Store (ec);
+ args.Add (new Argument (temp));
+ } else {
+ args.Add (new Argument (source));
+ }
}
- Arguments args = new Arguments (1);
- args.Add (new Argument (my_source));
-
Invocation.EmitCall (ec, InstanceExpression, Setter, args, loc, false, prepared);
if (temp != null) {
{
if (right_side == EmptyExpression.OutAccess.Instance) {
// TODO: best_candidate can be null at this point
- if (best_candidate != null && ec.CurrentBlock.Toplevel.GetParameterReference (best_candidate.Name, loc) is MemberAccess) {
+ INamedBlockVariable variable = null;
+ if (best_candidate != null && ec.CurrentBlock.ParametersBlock.TopBlock.GetLocalName (best_candidate.Name, ec.CurrentBlock, ref variable) && variable is Linq.RangeVariable) {
ec.Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter",
best_candidate.Name);
} else {
bool ResolveSetter (ResolveContext rc)
{
if (!best_candidate.HasSet) {
- if (rc.CurrentBlock.Toplevel.GetParameterReference (best_candidate.Name, loc) is MemberAccess) {
- rc.Report.Error (1947, loc, "A range variable `{0}' cannot be assigned to. Consider using `let' clause to store the value",
- best_candidate.Name);
- } else {
- rc.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read-only)",
- GetSignatureForError ());
- }
+ rc.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read-only)",
+ GetSignatureForError ());
return false;
}
public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original)
{
//
- // If the event is local to this class, we transform ourselves into a FieldExpr
+ // If the event is local to this class and we are not lhs of +=/-= we transform ourselves into a FieldExpr
//
+ if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) {
+ if (spec.BackingField != null &&
+ (spec.DeclaringType == ec.CurrentType || TypeManager.IsNestedChildOf (ec.CurrentType, spec.DeclaringType))) {
- if (spec.DeclaringType == ec.CurrentType ||
- TypeManager.IsNestedChildOf(ec.CurrentType, spec.DeclaringType)) {
-
- // TODO: Breaks dynamic binder as currect context fields are imported and not compiled
- // EventField mi = spec.MemberDefinition as EventField;
-
- if (spec.BackingField != null) {
spec.MemberDefinition.SetIsUsed ();
if (!ec.IsObsolete) {
AttributeTester.Report_ObsoleteMessage (oa, spec.GetSignatureForError (), loc, ec.Report);
}
- if ((spec.Modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0 && !ec.HasSet (ResolveContext.Options.CompoundAssignmentScope))
+ if ((spec.Modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
Error_AssignmentEventOnly (ec);
-
+
FieldExpr ml = new FieldExpr (spec.BackingField, loc);
InstanceExpression = null;
-
+
return ml.ResolveMemberAccess (ec, left, original);
}
- }
- if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope))
Error_AssignmentEventOnly (ec);
+ }
return base.ResolveMemberAccess (ec, left, original);
}
}
}
- public class TemporaryVariable : VariableReference
+ public class TemporaryVariableReference : VariableReference
{
- LocalInfo li;
+ public class Declarator : Statement
+ {
+ TemporaryVariableReference variable;
+
+ public Declarator (TemporaryVariableReference variable)
+ {
+ this.variable = variable;
+ loc = variable.loc;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ variable.li.CreateBuilder (ec);
+ }
+
+ protected override void CloneTo (CloneContext clonectx, Statement target)
+ {
+ // Nothing
+ }
+ }
+
+ LocalVariable li;
- public TemporaryVariable (TypeSpec type, Location loc)
+ public TemporaryVariableReference (LocalVariable li, Location loc)
{
- this.type = type;
+ this.li = li;
+ this.type = li.Type;
this.loc = loc;
}
+ public LocalVariable LocalInfo {
+ get {
+ return li;
+ }
+ }
+
+ public static TemporaryVariableReference Create (TypeSpec type, Block block, Location loc)
+ {
+ var li = LocalVariable.CreateCompilerGenerated (type, block, loc);
+ return new TemporaryVariableReference (li, loc);
+ }
+
public override Expression CreateExpressionTree (ResolveContext ec)
{
throw new NotSupportedException ("ET");
{
eclass = ExprClass.Variable;
- TypeExpr te = new TypeExpression (type, loc);
- li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
- if (!li.Resolve (ec))
- return null;
-
//
// Don't capture temporary variables except when using
// iterator redirection
public override void Emit (EmitContext ec)
{
+ li.CreateBuilder (ec);
+
Emit (ec, false);
}
public void EmitAssign (EmitContext ec, Expression source)
{
+ li.CreateBuilder (ec);
+
EmitAssign (ec, source, false, false);
}
///
class VarExpr : SimpleName
{
- // Used for error reporting only
- int initializers_count;
-
public VarExpr (Location loc)
: base ("var", loc)
{
- initializers_count = 1;
- }
-
- public int VariableInitializersCount {
- set {
- this.initializers_count = value;
- }
}
public bool InferType (ResolveContext ec, Expression right_side)
else
ec.Compiler.Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration");
}
-
- public override TypeExpr ResolveAsContextualType (IMemberContext rc, bool silent)
- {
- TypeExpr te = base.ResolveAsContextualType (rc, true);
- if (te != null)
- return te;
-
- if (RootContext.Version < LanguageVersion.V_3)
- rc.Compiler.Report.FeatureIsNotAvailable (loc, "implicitly typed local variable");
-
- if (initializers_count == 1)
- return null;
-
- if (initializers_count > 1) {
- rc.Compiler.Report.Error (819, loc, "An implicitly typed local variable declaration cannot include multiple declarators");
- initializers_count = 1;
- return null;
- }
-
- if (initializers_count == 0) {
- initializers_count = 1;
- rc.Compiler.Report.Error (818, loc, "An implicitly typed local variable declarator must include an initializer");
- return null;
- }
-
- return null;
- }
}
}