📄 ecore.cs
字号:
StringBuilder sb = new StringBuilder (valid [0]); for (int i = 1; i < count - 1; i++) { sb.Append ("', `"); sb.Append (valid [i]); } if (count > 1) { sb.Append ("' or `"); sb.Append (valid [count - 1]); } Report.Error (119, loc, "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb); } public static void UnsafeError (Location loc) { Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context"); } // // Load the object from the pointer. // public static void LoadFromPtr (ILGenerator ig, Type t) { if (t == TypeManager.int32_type) ig.Emit (OpCodes.Ldind_I4); else if (t == TypeManager.uint32_type) ig.Emit (OpCodes.Ldind_U4); else if (t == TypeManager.short_type) ig.Emit (OpCodes.Ldind_I2); else if (t == TypeManager.ushort_type) ig.Emit (OpCodes.Ldind_U2); else if (t == TypeManager.char_type) ig.Emit (OpCodes.Ldind_U2); else if (t == TypeManager.byte_type) ig.Emit (OpCodes.Ldind_U1); else if (t == TypeManager.sbyte_type) ig.Emit (OpCodes.Ldind_I1); else if (t == TypeManager.uint64_type) ig.Emit (OpCodes.Ldind_I8); else if (t == TypeManager.int64_type) ig.Emit (OpCodes.Ldind_I8); else if (t == TypeManager.float_type) ig.Emit (OpCodes.Ldind_R4); else if (t == TypeManager.double_type) ig.Emit (OpCodes.Ldind_R8); else if (t == TypeManager.bool_type) ig.Emit (OpCodes.Ldind_I1); else if (t == TypeManager.intptr_type) ig.Emit (OpCodes.Ldind_I); else if (TypeManager.IsEnumType (t)) { if (t == TypeManager.enum_type) ig.Emit (OpCodes.Ldind_Ref); else LoadFromPtr (ig, TypeManager.EnumToUnderlying (t)); } else if (t.IsValueType) ig.Emit (OpCodes.Ldobj, t); else if (t.IsPointer) ig.Emit (OpCodes.Ldind_I); else ig.Emit (OpCodes.Ldind_Ref); } // // The stack contains the pointer and the value of type `type' // public static void StoreFromPtr (ILGenerator ig, Type type) { if (TypeManager.IsEnumType (type)) type = TypeManager.EnumToUnderlying (type); if (type == TypeManager.int32_type || type == TypeManager.uint32_type) ig.Emit (OpCodes.Stind_I4); else if (type == TypeManager.int64_type || type == TypeManager.uint64_type) ig.Emit (OpCodes.Stind_I8); else if (type == TypeManager.char_type || type == TypeManager.short_type || type == TypeManager.ushort_type) ig.Emit (OpCodes.Stind_I2); else if (type == TypeManager.float_type) ig.Emit (OpCodes.Stind_R4); else if (type == TypeManager.double_type) ig.Emit (OpCodes.Stind_R8); else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type || type == TypeManager.bool_type) ig.Emit (OpCodes.Stind_I1); else if (type == TypeManager.intptr_type) ig.Emit (OpCodes.Stind_I); else if (type.IsValueType) ig.Emit (OpCodes.Stobj, type); else ig.Emit (OpCodes.Stind_Ref); } // // Returns the size of type `t' if known, otherwise, 0 // public static int GetTypeSize (Type t) { t = TypeManager.TypeToCoreType (t); if (t == TypeManager.int32_type || t == TypeManager.uint32_type || t == TypeManager.float_type) return 4; else if (t == TypeManager.int64_type || t == TypeManager.uint64_type || t == TypeManager.double_type) return 8; else if (t == TypeManager.byte_type || t == TypeManager.sbyte_type || t == TypeManager.bool_type) return 1; else if (t == TypeManager.short_type || t == TypeManager.char_type || t == TypeManager.ushort_type) return 2; else if (t == TypeManager.decimal_type) return 16; else return 0; } public static void Error_NegativeArrayIndex (Location loc) { Report.Error (248, loc, "Cannot create an array with a negative size"); } protected void Error_CannotCallAbstractBase (string name) { Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name); } // // Converts `source' to an int, uint, long or ulong. // public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc) { Expression target; bool old_checked = ec.CheckState; ec.CheckState = true; target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc); if (target == null){ target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc); if (target == null){ target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc); if (target == null){ target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc); if (target == null) source.Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false); } } } ec.CheckState = old_checked; // // Only positive constants are allowed at compile time // if (target is Constant){ if (target is IntConstant){ if (((IntConstant) target).Value < 0){ Error_NegativeArrayIndex (loc); return null; } } if (target is LongConstant){ if (((LongConstant) target).Value < 0){ Error_NegativeArrayIndex (loc); return null; } } } return target; } } /// <summary> /// This is just a base class for expressions that can /// appear on statements (invocations, object creation, /// assignments, post/pre increment and decrement). The idea /// being that they would support an extra Emition interface that /// does not leave a result on the stack. /// </summary> public abstract class ExpressionStatement : Expression { public virtual ExpressionStatement ResolveStatement (EmitContext ec) { Expression e = Resolve (ec); if (e == null) return null; ExpressionStatement es = e as ExpressionStatement; if (es == null) Error (201, "Only assignment, call, increment, decrement and new object " + "expressions can be used as a statement"); return es; } /// <summary> /// Requests the expression to be emitted in a `statement' /// context. This means that no new value is left on the /// stack after invoking this method (constrasted with /// Emit that will always leave a value on the stack). /// </summary> public abstract void EmitStatement (EmitContext ec); } /// <summary> /// This kind of cast is used to encapsulate the child /// whose type is child.Type into an expression that is /// reported to return "return_type". This is used to encapsulate /// expressions which have compatible types, but need to be dealt /// at higher levels with. /// /// For example, a "byte" expression could be encapsulated in one /// of these as an "unsigned int". The type for the expression /// would be "unsigned int". /// /// </summary> public class EmptyCast : Expression { protected Expression child; public Expression Child { get { return child; } } public EmptyCast (Expression child, Type return_type) { eclass = child.eclass; loc = child.Location; type = return_type; this.child = child; } public override Expression DoResolve (EmitContext ec) { // This should never be invoked, we are born in fully // initialized state. return this; } public override void Emit (EmitContext ec) { child.Emit (ec); } } /// <summary> /// This is a numeric cast to a Decimal /// </summary> public class CastToDecimal : EmptyCast { MethodInfo conversion_operator; public CastToDecimal (Expression child) : this (child, false) { } public CastToDecimal (Expression child, bool find_explicit) : base (child, TypeManager.decimal_type) { conversion_operator = GetConversionOperator (find_explicit); if (conversion_operator == null) throw new InternalErrorException ("Outer conversion routine is out of sync"); } // Returns the implicit operator that converts from // 'child.Type' to System.Decimal. MethodInfo GetConversionOperator (bool find_explicit) { string operator_name = find_explicit ? "op_Explicit" : "op_Implicit"; MemberInfo [] mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method, BindingFlags.Static | BindingFlags.Public, operator_name, null); foreach (MethodInfo oper in mi) { ParameterData pd = TypeManager.GetParameterData (oper); if (pd.ParameterType (0) == child.Type && oper.ReturnType == type) return oper; } return null; } public override void Emit (EmitContext ec) { ILGenerator ig = ec.ig; child.Emit (ec); ig.Emit (OpCodes.Call, conversion_operator); } } /// <summary> /// This is an explicit numeric cast from a Decimal /// </summary> public class CastFromDecimal : EmptyCast { static IDictionary operators; public CastFromDecimal (Expression child, Type return_type) : base (child, return_type) { if (child.Type != TypeManager.decimal_type) throw new InternalErrorException ( "The expected type is Decimal, instead it is " + child.Type.FullName); } // Returns the explicit operator that converts from an // express of type System.Decimal to 'type'. public Expression Resolve () { if (operators == null) { MemberInfo[] all_oper = TypeManager.MemberLookup (TypeManager.decimal_type, TypeManager.decimal_type, TypeManager.decimal_type, MemberTypes.Method, BindingFlags.Static | BindingFlags.Public, "op_Explicit", null); operators = new System.Collections.Specialized.HybridDictionary (); foreach (MethodInfo oper in all_oper) { ParameterData pd = TypeManager.GetParameterData (oper); if (pd.ParameterType (0) == TypeManager.decimal_type) operators.Add (oper.ReturnType, oper); } } return operators.Contains (type) ? this : null; } public override void Emit (EmitContext ec) { ILGenerator ig = ec.ig; child.Emit (ec); ig.Emit (OpCodes.Call, (MethodInfo)operators [type]); } } // // We need to special case this since an empty cast of // a NullLiteral is still a Constant // public class NullCast : Constant { public Constant child; public NullCast (Constant child, Type return_type): base (Location.Null) { eclass = child.eclass; type = return_type; this.child = child; } override public string AsString () { return "null"; } public override object GetValue () { return null; } public override Expression DoResolve (EmitContext ec) { // This should never be invoked, we are born in fully // initialized state. return this; } public override void Emit (EmitContext ec) { child.Emit (ec); } public override Constant Increment () { throw new NotSupportedException (); } public override bool IsDefaultValue { get { throw new NotImplementedException (); } } public override bool IsNegative { get { return false; } } public override Constant Reduce (EmitContext ec, Type target_type) { if (type == target_type) return child.Reduce (ec, target_type); return null; } } /// <summary> /// This class is used to wrap literals which belong inside Enums /// </summary> public class EnumConstant : Constant { public Constant Child; public EnumConstant (Constant child, Type enum_type): base (child.Location) { eclass = child.eclass; this.Child = child; type = enum_type; } public override Expression DoResolve (EmitContext ec) { // This should never be invoked, we are born in fully // initialized state. return this; } public override void Emit (EmitContext ec) { Child.Emit (ec); } public override string GetSignatureForError() { return TypeManager.CSharpName (Type); } public override object GetValue () { return Child.GetValue (); } public override object GetTypedValue () { // FIXME: runtime is not ready to work with just emited enums if (!RootContext.StdLib) { return Child.GetValue ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -