public override Expression DoResolve(ResolveContext rc) { if (_resolved) { return(this); } expr = expr.DoResolve(rc); if (expr == null) { return(null); } var pc = expr.Type as PointerTypeSpec; if (pc == null) { rc.Report.Error(0, loc, "The * or -> operator must be applied to a pointer"); return(null); } ResolvedType = pc.ElementType; if (ResolvedType.Kind == TypeKind.Void) { rc.Report.Error(0, loc, "The operation in question is undefined on void pointers"); return(null); } eclass = ExprClass.Variable; return(this); }
public override VSC.AST.Expression DoResolve(VSC.TypeSystem.Resolver.ResolveContext rc) { if (_resolved) { return(this); } ResolveContext oldResolver = rc; try { rc = rc.WithCheckForOverflow(true); Expr = Expr.DoResolve(rc); } finally { rc = oldResolver; } if (Expr == null) { return(null); } //TODO:Anonymous if (Expr is Constant || Expr is MethodGroupExpression || /*Expr is AnonymousMethodExpression ||*/ Expr is DefaultValueExpression) { return(Expr); } eclass = Expr.eclass; ResolvedType = Expr.Type; _resolved = true; return(this); }
public override VSC.AST.Expression DoResolve(VSC.TypeSystem.Resolver.ResolveContext rc) { UnaryOperatorType op = UnaryOperatorType.PostIncrement; if (mode == Mode.PreIncrement) { op = UnaryOperatorType.PreIncrement; } else if (mode == Mode.PreDecrement) { op = UnaryOperatorType.Decrement; } else if (mode == Mode.PostDecrement) { op = UnaryOperatorType.PostDecrement; } expr = expr.DoResolve(rc); if (expr == null) { return(null); } // ++/-- on pointer variables of all types except void* if (expr.Type is PointerTypeSpec) { if (((PointerTypeSpec)expr.Type).ElementType.Kind == TypeKind.Void) { rc.Report.Error(0, loc, "The operation in question is undefined on void pointers"); return(null); } } if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) { expr = expr.DoResolveLeftValue(rc, expr); } else { rc.Report.Error(0, loc, "The operand of an increment or decrement operator must be a variable, property or indexer"); } operation = new UnaryExpression(op, expr, loc).DoResolve(rc); if (operation == null) { return(null); } _resolved = true; ResolvedType = operation.Type; eclass = ExprClass.Value; return(this); }
public override Expression Resolve(ResolveContext rc) { if (_resolved) { return(this); } else { Expression targetRR = expr.DoResolve(rc); IList <IType> typeArgs = typeArgumentsrefs.Resolve(rc.CurrentTypeResolveContext); if (LookForAttribute) { var wa = ResolveMemberAccess(rc, targetRR, name + "Attribute", typeArgs, lookupMode); if (wa == null || wa.IsError) { wa = ResolveMemberAccess(rc, targetRR, name, typeArgs, lookupMode); if (wa == null || wa.IsError) { rc.Report.Error(148, loc, "Type `{0}' does not contain a definition for `{1}' and no extension method `{1}' of type `{0}' could be found.", expr.GetSignatureForError(), GetSignatureForError()); } } LookForAttribute = false; return(wa); } else { var wa = ResolveMemberAccess(rc, targetRR, name, typeArgs, lookupMode); if (wa == null || wa.IsError) { rc.Report.Error(148, loc, "Type `{0}' does not contain a definition for `{1}' and no extension method `{1}' of type `{0}' could be found.", expr.GetSignatureForError(), GetSignatureForError()); } return(wa); } } }
public override Expression DoResolve(ResolveContext rc) { if (_resolved) { return(this); } count = count.DoResolve(rc); if (count == null) { return(null); } if (!count.Type.IsKnownType(KnownTypeCode.UInt32)) { count = new CastExpression(KnownTypeReference.UInt32.Resolve(rc), count).DoResolve(rc); if (count == null) { return(null); } } Constant c = count as Constant; if (c != null && c.IsNegative) { rc.Report.Error(0, loc, "Cannot use a negative size with stackalloc"); } if (rc.HasAny(ResolveContext.Options.CatchScope | ResolveContext.Options.FinallyScope)) { rc.Report.Error(0, loc, "Cannot use stackalloc in finally or catch"); } otype = texpr.ResolveAsType(rc); if (otype == null) { return(null); } ResolvedType = new PointerTypeSpec(otype); _resolved = true; eclass = ExprClass.Value; return(this); }
public override Expression DoResolve(ResolveContext rc) { if (_resolved) { return(this); } expr = expr.DoResolve(rc); if (expr == null) { return(null); } ResolvedType = expr.Type; _resolved = true; eclass = expr.eclass; return(this); }
public void Resolve(VSC.TypeSystem.Resolver.ResolveContext rc) { // Verify that the argument is readable if (ArgType != AType.Out) { Expr = Expr.DoResolve(rc); } // Verify that the argument is writeable if (Expr != null && IsByRef) { Expr = Expr.DoResolveLeftValue(rc, EmptyExpression.OutAccess); } if (Expr == null) { Expr = Expression.ErrorResult; } }
protected virtual Expression ResolveArrayElement(ResolveContext ec, Expression element) { element = element.DoResolve(ec); if (element == null) { return(null); } if (element is CompoundAssign.TargetExpression) { if (first_emit != null) { throw new InternalErrorException("Can only handle one mutator at a time"); } first_emit = element; element = first_emit_temp = new LocalTemporary(element.Type); } return(new CastExpression(array_element_type, element, loc).DoResolve(ec)); }
// // We perform some simple tests, and then to "split" the emit and store // code we create an instance of a different class, and return that. // Expression ResolveAccessExpression(ResolveContext rc, bool conditionalAccessReceiver) { Expr = Expr.DoResolve(rc); if (Expr == null) { return(null); } ResolvedType = Expr.Type; if (ConditionalAccess && !IsNullPropagatingValid(ResolvedType)) { rc.Report.Error(0, loc, "The `{0}' operator cannot be applied to operand of type `{1}'", "?", ResolvedType.ToString()); return(null); } string[] argumentNames; Expression[] arguments = Arguments.GetArguments(out argumentNames); return(ResolveIndexer(rc, Expr, arguments, argumentNames)); }
public override Expression DoResolve(ResolveContext rc) { if (_resolved) { return(this); } Expr = Expr.DoResolve(rc); if (Expr == null) { return(null); } ITypeDefinition inputTypeDef = Expr.Type.GetDefinition(); if (Expr.IsCompileTimeConstant && Expr is Constant && inputTypeDef != null) { // Special cases for int.MinValue and long.MinValue if (inputTypeDef.KnownTypeCode == KnownTypeCode.UInt32 && 2147483648.Equals(Expr.ConstantValue)) { return(Constant.CreateConstantFromValue(rc, rc.Compilation.FindType(KnownTypeCode.Int32), -2147483648, Expr.Location)); } else if (inputTypeDef.KnownTypeCode == KnownTypeCode.UInt64 && 9223372036854775808.Equals(Expr.ConstantValue)) { return(Constant.CreateConstantFromValue(rc, rc.Compilation.FindType(KnownTypeCode.Int64), -9223372036854775808, Expr.Location)); } } Expression rr = ResolveUnaryOperator(rc, Oper, Expr); if (rr.IsError) { rc.Report.Error(0, loc, "The `{0}' operator cannot be applied to operand of type `{1}'", OperName(Oper), rr.Type.ToString()); return(null); } rr.eclass = ExprClass.Value; _resolved = true; return(rr); }
public override Expression DoResolve(ResolveContext rc) { if (_resolved) { return(this); } left = left.DoResolve(rc); right = right.DoResolve(rc); if (left == null || right == null) { return(null); } Expression expr = ResolveBinaryOperator(rc, oper, left, right); if (expr == null) { rc.Report.Error(0, loc, "Operator `{0}' cannot be applied to operands of type `{1}' and `{2}'", OperName(oper), left.Type.ToString(), right.Type.ToString()); return(null); } expr.eclass = ExprClass.Value; return(expr); }
protected Expression ResolveCommon(ResolveContext rc) { expr = expr.DoResolve(rc); if (expr == null) { return(null); } ResolveProbeType(rc); if (probe_type_expr == null) { return(this); } if (rc.IsStaticType(probe_type_expr)) { rc.Report.Error(250, loc, "The second operand of `is' or `as' operator cannot be static type `{0}'", probe_type_expr.ToString()); return(null); } if (expr.Type is PointerTypeSpec || probe_type_expr is PointerTypeSpec) { rc.Report.Error(251, loc, "The `{0}' operator cannot be applied to an operand of pointer type", OperatorName); return(null); } //TODO:Method Group type & anonymous method type if (/*expr.Type == InternalType.AnonymousMethod ||*/ expr is MethodGroupExpression) { rc.Report.Error(837, loc, "The `{0}' operator cannot be applied to a lambda expression, anonymous method, or method group", OperatorName); return(null); } return(this); }
bool CheckIndices(ResolveContext ec, ArrayInitializer probe, int idx, bool specified_dims, int child_bounds) { if (initializers != null && bounds == null) { // // We use this to store all the data values in the order in which we // will need to store them in the byte blob later // array_data = new List <Expression>(probe.Count); bounds = new Dictionary <int, int>(); } if (specified_dims) { Expression a = arguments[idx]; a = a.DoResolve(ec); if (a == null) { return(false); } a = ConvertExpressionToArrayIndex(ec, a); if (a == null) { return(false); } arguments[idx] = a; if (initializers != null) { Constant c = a as Constant; if (c == null && a is CastExpression) { c = ((CastExpression)a).Expr as Constant; } if (c == null) { ec.Report.Error(0, a.Location, "A constant value is expected"); return(false); } int value; try { value = System.Convert.ToInt32(c.GetValue()); } catch { ec.Report.Error(0, a.Location, "A constant value is expected"); return(false); } // TODO: probe.Count does not fit ulong in if (value != probe.Count) { ec.Report.Error(0, loc, "An array initializer of length `{0}' was expected", value.ToString()); return(false); } bounds[idx] = value; } } if (initializers == null) { return(true); } for (int i = 0; i < probe.Count; ++i) { var o = probe[i]; if (o is ArrayInitializer) { var sub_probe = o as ArrayInitializer; if (idx + 1 >= dimensions) { ec.Report.Error(0, loc, "Array initializers can only be used in a variable or field initializer. Try using a new expression instead"); return(false); } // When we don't have explicitly specified dimensions, record whatever dimension we first encounter at each level if (!bounds.ContainsKey(idx + 1)) { bounds[idx + 1] = sub_probe.Count; } if (bounds[idx + 1] != sub_probe.Count) { ec.Report.Error(0, sub_probe.Location, "An array initializer of length `{0}' was expected", bounds[idx + 1].ToString()); return(false); } bool ret = CheckIndices(ec, sub_probe, idx + 1, specified_dims, child_bounds - 1); if (!ret) { return(false); } } else if (child_bounds > 1) { ec.Report.Error(0, o.Location, "A nested array initializer was expected"); } else { Expression element = ResolveArrayElement(ec, o); if (element == null) { continue; } array_data.Add(element); } } return(true); }
public override VSC.AST.Expression DoResolve(VSC.TypeSystem.Resolver.ResolveContext rc) { List <string> element_names = null; for (int i = 0; i < initializers.Count; ++i) { Expression initializer = initializers[i]; ElementInitializer element_initializer = initializer as ElementInitializer; if (i == 0) { if (element_initializer != null) { element_names = new List <string>(initializers.Count); element_names.Add(element_initializer.Name); } //else if (initializer is CompletingExpression)//TODO:Add complete //{ // initializer.Resolve(ec); // throw new InternalErrorException("This line should never be reached"); //} else { var t = rc.CurrentObjectInitializerType; // LAMESPEC: The collection must implement IEnumerable only, no dynamic support if (!t.Implements(KnownTypeReference.IEnumerable.Resolve(rc))) { rc.Report.Error(0, loc, "A field or property `{0}' cannot be initialized with a collection " + "object initializer because type `{1}' does not implement `{2}' interface", rc.CurrentObjectInitializer.GetSignatureForError(), rc.CurrentObjectInitializerType.ToString(), KnownTypeReference.IEnumerable.ToString()); return(null); } is_collection_initialization = true; } } else { if (is_collection_initialization != (element_initializer == null)) { rc.Report.Error(0, initializer.Location, "Inconsistent `{0}' member declaration", is_collection_initialization ? "collection initializer" : "object initializer"); continue; } if (!is_collection_initialization) { if (element_names.Contains(element_initializer.Name)) { rc.Report.Error(0, element_initializer.Location, "An object initializer includes more than one member `{0}' initialization", element_initializer.Name); } else { element_names.Add(element_initializer.Name); } } } Expression e = initializer.DoResolve(rc); if (e == EmptyExpressionStatement.Instance) { initializers.RemoveAt(i--); } else { initializers[i] = e; } } ResolvedType = rc.CurrentObjectInitializerType; if (is_collection_initialization) { if (ResolvedType is ElementTypeSpec) { rc.Report.Error(0, loc, "Cannot initialize object of type `{0}' with a collection initializer", ResolvedType.ToString()); } } eclass = ExprClass.Variable; return(this); }
public override VSC.AST.Expression DoResolve(VSC.TypeSystem.Resolver.ResolveContext rc) { expr = expr.DoResolve(rc); true_expr = true_expr.DoResolve(rc); false_expr = false_expr.DoResolve(rc); if (true_expr == null || false_expr == null || expr == null) { return(null); } eclass = ExprClass.Value; // V# 4.0 spec §7.14: Conditional operator bool isValid; IType resultType; if (true_expr.Type.Kind == TypeKind.Dynamic || false_expr.Type.Kind == TypeKind.Dynamic) { resultType = SpecialTypeSpec.Dynamic; isValid = rc.TryConvert(ref true_expr, resultType) & rc.TryConvert(ref false_expr, resultType); } else if (rc.HasType(true_expr) && rc.HasType(false_expr)) { Conversion t2f = rc.conversions.ImplicitConversion(true_expr, false_expr.Type); Conversion f2t = rc.conversions.ImplicitConversion(false_expr, true_expr.Type); // The operator is valid: // a) if there's a conversion in one direction but not the other // b) if there are conversions in both directions, and the types are equivalent if (rc.IsBetterConditionalConversion(t2f, f2t)) { resultType = false_expr.Type; isValid = true; true_expr = rc.Convert(true_expr, resultType, t2f); } else if (rc.IsBetterConditionalConversion(f2t, t2f)) { resultType = true_expr.Type; isValid = true; false_expr = rc.Convert(false_expr, resultType, f2t); } else { resultType = true_expr.Type; isValid = true_expr.Type.Equals(false_expr.Type); if (!isValid) { _resolved = true; ResolvedType = resultType; rc.Report.Error(248, true_expr.Location, "Type of conditional expression cannot be determined as `{0}' and `{1}' convert implicitly to each other", true_expr.Type.ToString(), false_expr.Type.ToString()); return(this); } } } else if (rc.HasType(true_expr)) { resultType = true_expr.Type; isValid = rc.TryConvert(ref false_expr, resultType); } else if (rc.HasType(false_expr)) { resultType = false_expr.Type; isValid = rc.TryConvert(ref true_expr, resultType); } else { return(ErrorResult); } expr = rc.ResolveCondition(expr); if (isValid) { if (expr.IsCompileTimeConstant && true_expr.IsCompileTimeConstant && false_expr.IsCompileTimeConstant) { bool?val = expr.ConstantValue as bool?; if (val == true) { return(true_expr); } else if (val == false) { return(false_expr); } } _resolved = true; this.ResolvedType = resultType; return(this); } else { rc.Report.Error(249, true_expr.Location, "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'", true_expr.Type.ToString(), false_expr.Type.ToString()); } return(this); }