📄 ecore.cs
字号:
if (e != null){ if (e.eclass == ExprClass.Invalid) throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve"); if (e.eclass == ExprClass.MethodGroup) { ((MethodGroupExpr) e).ReportUsageError (); return null; } if (e.type == null) throw new Exception ("Expression " + e + " did not set its type after Resolve"); } return e; } /// <summary> /// Emits the code for the expression /// </summary> /// /// <remarks> /// The Emit method is invoked to generate the code /// for the expression. /// </remarks> public abstract void Emit (EmitContext ec); public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue) { Emit (ec); ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target); } /// <summary> /// Protected constructor. Only derivate types should /// be able to be created /// </summary> protected Expression () { eclass = ExprClass.Invalid; type = null; } /// <summary> /// Returns a literalized version of a literal FieldInfo /// </summary> /// /// <remarks> /// The possible return values are: /// IntConstant, UIntConstant /// LongLiteral, ULongConstant /// FloatConstant, DoubleConstant /// StringConstant /// /// The value returned is already resolved. /// </remarks> public static Constant Constantify (object v, Type t) { if (t == TypeManager.int32_type) return new IntConstant ((int) v, Location.Null); else if (t == TypeManager.uint32_type) return new UIntConstant ((uint) v, Location.Null); else if (t == TypeManager.int64_type) return new LongConstant ((long) v, Location.Null); else if (t == TypeManager.uint64_type) return new ULongConstant ((ulong) v, Location.Null); else if (t == TypeManager.float_type) return new FloatConstant ((float) v, Location.Null); else if (t == TypeManager.double_type) return new DoubleConstant ((double) v, Location.Null); else if (t == TypeManager.string_type) return new StringConstant ((string) v, Location.Null); else if (t == TypeManager.short_type) return new ShortConstant ((short)v, Location.Null); else if (t == TypeManager.ushort_type) return new UShortConstant ((ushort)v, Location.Null); else if (t == TypeManager.sbyte_type) return new SByteConstant ((sbyte)v, Location.Null); else if (t == TypeManager.byte_type) return new ByteConstant ((byte)v, Location.Null); else if (t == TypeManager.char_type) return new CharConstant ((char)v, Location.Null); else if (t == TypeManager.bool_type) return new BoolConstant ((bool) v, Location.Null); else if (t == TypeManager.decimal_type) return new DecimalConstant ((decimal) v, Location.Null); else if (TypeManager.IsEnumType (t)){ Type real_type = TypeManager.TypeToCoreType (v.GetType ()); if (real_type == t) real_type = System.Enum.GetUnderlyingType (real_type); Constant e = Constantify (v, real_type); return new EnumConstant (e, t); } else if (v == null && !TypeManager.IsValueType (t)) return new NullLiteral (Location.Null); else throw new Exception ("Unknown type for constant (" + t + "), details: " + v); } /// <summary> /// Returns a fully formed expression after a MemberLookup /// </summary> /// public static Expression ExprClassFromMemberInfo (EmitContext ec, MemberInfo mi, Location loc) { if (mi is EventInfo) return new EventExpr ((EventInfo) mi, loc); else if (mi is FieldInfo) return new FieldExpr ((FieldInfo) mi, loc); else if (mi is PropertyInfo) return new PropertyExpr (ec, (PropertyInfo) mi, loc); else if (mi is Type){ return new TypeExpression ((System.Type) mi, loc); } return null; } protected static ArrayList almostMatchedMembers = new ArrayList (4); // // FIXME: Probably implement a cache for (t,name,current_access_set)? // // This code could use some optimizations, but we need to do some // measurements. For example, we could use a delegate to `flag' when // something can not any longer be a method-group (because it is something // else). // // Return values: // If the return value is an Array, then it is an array of // MethodBases // // If the return value is an MemberInfo, it is anything, but a Method // // null on error. // // FIXME: When calling MemberLookup inside an `Invocation', we should pass // the arguments here and have MemberLookup return only the methods that // match the argument count/type, unlike we are doing now (we delay this // decision). // // This is so we can catch correctly attempts to invoke instance methods // from a static body (scan for error 120 in ResolveSimpleName). // // // FIXME: Potential optimization, have a static ArrayList // public static Expression MemberLookup (EmitContext ec, Type queried_type, string name, MemberTypes mt, BindingFlags bf, Location loc) { return MemberLookup (ec, ec.ContainerType, null, queried_type, name, mt, bf, loc); } // // 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 (EmitContext ec, Type container_type, Type qualifier_type, Type queried_type, string name, MemberTypes mt, BindingFlags bf, Location loc) { almostMatchedMembers.Clear (); MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type, queried_type, mt, bf, name, almostMatchedMembers); if (mi == null) return null; int count = mi.Length; if (mi [0] is MethodBase) return new MethodGroupExpr (mi, loc); if (count > 1) return null; return ExprClassFromMemberInfo (ec, mi [0], loc); } public const MemberTypes AllMemberTypes = MemberTypes.Constructor | MemberTypes.Event | MemberTypes.Field | MemberTypes.Method | MemberTypes.NestedType | MemberTypes.Property; public const BindingFlags AllBindingFlags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance; public static Expression MemberLookup (EmitContext ec, Type queried_type, string name, Location loc) { return MemberLookup (ec, ec.ContainerType, null, queried_type, name, AllMemberTypes, AllBindingFlags, loc); } public static Expression MemberLookup (EmitContext ec, Type qualifier_type, Type queried_type, string name, Location loc) { return MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type, name, AllMemberTypes, AllBindingFlags, loc); } public static Expression MethodLookup (EmitContext ec, Type queried_type, string name, Location loc) { return MemberLookup (ec, ec.ContainerType, null, queried_type, name, MemberTypes.Method, AllBindingFlags, loc); } /// <summary> /// This is a wrapper for MemberLookup that is not used to "probe", but /// to find a final definition. If the final definition is not found, we /// look for private members and display a useful debugging message if we /// find it. /// </summary> public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type, Type queried_type, string name, Location loc) { return MemberLookupFinal (ec, qualifier_type, queried_type, name, AllMemberTypes, AllBindingFlags, loc); } public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type, Type queried_type, string name, MemberTypes mt, BindingFlags bf, Location loc) { Expression e; int errors = Report.Errors; e = MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc); if (e == null && errors == Report.Errors) // No errors were reported by MemberLookup, but there was an error. MemberLookupFailed (ec, qualifier_type, queried_type, name, null, true, loc); return e; } public static void MemberLookupFailed (EmitContext ec, Type qualifier_type, Type queried_type, string name, string class_name, bool complain_if_none_found, Location loc) { if (almostMatchedMembers.Count != 0) { for (int i = 0; i < almostMatchedMembers.Count; ++i) { MemberInfo m = (MemberInfo) almostMatchedMembers [i]; for (int j = 0; j < i; ++j) { if (m == almostMatchedMembers [j]) { m = null; break; } } if (m == null) continue; Type declaring_type = m.DeclaringType; Report.SymbolRelatedToPreviousError (m); if (qualifier_type == null) { Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'", TypeManager.CSharpName (m.DeclaringType), TypeManager.CSharpName (ec.ContainerType)); } else if (qualifier_type != ec.ContainerType && TypeManager.IsNestedFamilyAccessible (ec.ContainerType, declaring_type)) { // Although a derived class can access protected members of // its base class it cannot do so through an instance of the // base class (CS1540). If the qualifier_type is a base of the // ec.ContainerType and the lookup succeeds with the latter one, // then we are in this situation. Error_CannotAccessProtected (loc, m, qualifier_type, ec.ContainerType); } else { ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (m)); } } almostMatchedMembers.Clear (); return; } MemberInfo[] lookup = TypeManager.MemberLookup (queried_type, null, queried_type, AllMemberTypes, AllBindingFlags | BindingFlags.NonPublic, name, null); if (lookup == null) { if (!complain_if_none_found) return; if (class_name != null) Report.Error (103, loc, "The name `{0}' does not exist in the context of `{1}'", name, class_name); else Error_TypeDoesNotContainDefinition (loc, queried_type, name); return; } MemberList ml = TypeManager.FindMembers (queried_type, MemberTypes.Constructor, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, null, null); if (name == ".ctor" && ml.Count == 0) { Report.Error (143, loc, String.Format ("The type `{0}' has no constructors defined", TypeManager.CSharpName (queried_type))); return; } ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0])); } /// <summary> /// Returns an expression that can be used to invoke operator true /// on the expression if it exists. /// </summary> static public StaticCallExpr GetOperatorTrue (EmitContext ec, Expression e, Location loc) { return GetOperatorTrueOrFalse (ec, e, true, loc); } /// <summary> /// Returns an expression that can be used to invoke operator false /// on the expression if it exists. /// </summary> static public StaticCallExpr GetOperatorFalse (EmitContext ec, Expression e, Location loc) { return GetOperatorTrueOrFalse (ec, e, false, loc); } static StaticCallExpr GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc) { MethodBase method; Expression operator_group; operator_group = MethodLookup (ec, e.Type, is_true ? "op_True" : "op_False", loc); if (operator_group == null) return null; ArrayList arguments = new ArrayList (); arguments.Add (new Argument (e, Argument.AType.Expression)); method = Invocation.OverloadResolve ( ec, (MethodGroupExpr) operator_group, arguments, false, loc); if (method == null) return null; return new StaticCallExpr ((MethodInfo) method, arguments, loc); } /// <summary> /// Resolves the expression `e' into a boolean expression: either through /// an implicit conversion, or through an `operator true' invocation /// </summary> public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc) { e = e.Resolve (ec); if (e == null) return null; if (e.Type == TypeManager.bool_type) return e; Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, Location.Null); if (converted != null) return converted; // // If no implicit conversion to bool exists, try using `operator true' // converted = Expression.GetOperatorTrue (ec, e, loc); if (converted == null){ e.Error_ValueCannotBeConverted (loc, TypeManager.bool_type, false); return null; } return converted; } public virtual string ExprClassName { get { switch (eclass){ case ExprClass.Invalid: return "Invalid"; case ExprClass.Value: return "value"; case ExprClass.Variable: return "variable"; case ExprClass.Namespace: return "namespace"; case ExprClass.Type: return "type"; case ExprClass.MethodGroup: return "method group"; case ExprClass.PropertyAccess: return "property access"; case ExprClass.EventAccess: return "event access"; case ExprClass.IndexerAccess: return "indexer access"; case ExprClass.Nothing: return "null"; } throw new Exception ("Should not happen"); } } /// <summary> /// Reports that we were expecting `expr' to be of class `expected' /// </summary> public void Error_UnexpectedKind (EmitContext ec, string expected, Location loc) { Error_UnexpectedKind (ec, expected, ExprClassName, loc); } public void Error_UnexpectedKind (EmitContext ec, string expected, string was, Location loc) { string name = GetSignatureForError (); if (ec != null) name = ec.DeclSpace.GetSignatureForError () + '.' + name; Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected", name, was, expected); } public void Error_UnexpectedKind (ResolveFlags flags, Location loc) { string [] valid = new string [4]; int count = 0; if ((flags & ResolveFlags.VariableOrValue) != 0) { valid [count++] = "variable"; valid [count++] = "value"; } if ((flags & ResolveFlags.Type) != 0) valid [count++] = "type"; if ((flags & ResolveFlags.MethodGroup) != 0) valid [count++] = "method group"; if (count == 0) valid [count++] = "unknown";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -