internal static object DCArg(Variable v) { P6any o = v.Fetch(); var s = o.mo.setting; if (o is BoxObject <object> ) { return(Kernel.UnboxAny <object>(o)); } else if (o.IsDefined()) { if (o.Isa(s.StrMO)) { return((string)o.mo.mro_raw_Str.Get(v)); } else if (o.Isa(s.BoolMO)) { return((bool)o.mo.mro_raw_Bool.Get(v)); } else if (o.Isa(s.NumMO)) { double d = Kernel.UnboxAny <double>(o); if ((d % 1) == 0 && d <= int.MaxValue && d >= int.MinValue) { return((object)(int)d); } return((object)d); } else if (o.Isa(s.ListMO)) { VarDeque it = o.mo.mro_raw_iterator.Get(v); var lo = new List <object>(); while (Kernel.IterHasFlat(it, true)) { lo.Add(DCArg(it.Shift())); } return(lo.ToArray()); } else { return((int)o.mo.mro_raw_Numeric.Get(v)); } } else { return(null); } }
internal static object DCArg(Variable v) { P6any o = v.Fetch(); if (o is BoxObject <object> ) { return(Kernel.UnboxAny <object>(o)); } else if (o.IsDefined()) { if (o.Isa(Kernel.StrMO)) { return((string)o.mo.mro_raw_Str.Get(v)); } else if (o.Isa(Kernel.BoolMO)) { return((bool)o.mo.mro_raw_Bool.Get(v)); } else if (o.Isa(Kernel.ListMO)) { VarDeque it = o.mo.mro_raw_iterator.Get(v); var lo = new List <object>(); while (Kernel.IterHasFlat(it, true)) { lo.Add(DCArg(it.Shift())); } return(lo.ToArray()); } else { return((int)o.mo.mro_raw_Numeric.Get(v)); } } else { return(null); } }
internal static void SerializeNam(Variable v, StringBuilder sb, List <object> refs) { P6any o = v.Fetch(); if (o is BoxObject <int> ) /* includes bool */ { sb.Append(Kernel.UnboxAny <int>(o)); } else if (o is BoxObject <double> ) { sb.Append(Utils.N2S(Kernel.UnboxAny <double>(o))); } else if (o is BoxObject <string> ) { string s = Kernel.UnboxAny <string>(o); sb.Append('"'); foreach (char c in s) { if (c >= ' ' && c <= '~' && c != '\\' && c != '"') { sb.Append(c); } else { sb.Append("\\u"); sb.AppendFormat("{0:X4}", (int)c); } } sb.Append('"'); } else if (!o.IsDefined()) { sb.Append("null"); } else if (o.Isa(o.mo.setting.ListMO)) { VarDeque d = o.mo.mro_raw_iterator.Get(v); bool comma = false; sb.Append('['); while (Kernel.IterHasFlat(d, true)) { if (comma) { sb.Append(','); } SerializeNam(d.Shift(), sb, refs); comma = true; } sb.Append(']'); } else if (o is BoxObject <object> ) { sb.Append('!'); sb.Append(refs.Count); refs.Add(Kernel.UnboxAny <object>(o)); } else { throw new NieczaException("weird object in sub_finish " + o.mo.name); } }
public static bool CoerceArgument(out object clr, Type ty, Variable var) { P6any obj = var.Fetch(); clr = null; // type objects are typed nulls if (!obj.IsDefined()) { if (obj is BoxObject <object> ) { Type t = obj.mo.box_type; // is this enough? return(ty.IsAssignableFrom(t) && !ty.IsValueType && ty != typeof(void)); } else if (obj.mo == Kernel.MuMO || obj.mo == Kernel.AnyMO) { // untyped-ish null return(!ty.IsValueType && ty != typeof(void)); } else { // we'll pass this by value anyway clr = obj; return(ty.IsAssignableFrom(obj.GetType())); } } // in all other cases we're definitely passing a non-null value // Boolean values marshal to bool if (obj.Does(Kernel.BoolMO)) { clr = Kernel.UnboxAny <int>(obj) != 0; } // note, Bool ~~ Int ~~ Integral else if (obj.Does(Kernel.IntegralMO)) { // important type directed case! int small; BigInteger big; bool use_big = Builtins.GetAsInteger(var, out small, out big); if (ty == typeof(sbyte)) { clr = (!use_big && small >= sbyte.MinValue && small <= sbyte.MaxValue) ? (object)(sbyte)small : null; } else if (ty == typeof(byte)) { clr = (!use_big && small >= byte.MinValue && small <= byte.MaxValue) ? (object)(byte)small : null; } else if (ty == typeof(short)) { clr = (!use_big && small >= short.MinValue && small <= short.MaxValue) ? (object)(short)small : null; } else if (ty == typeof(ushort)) { clr = (!use_big && small >= ushort.MinValue && small <= ushort.MaxValue) ? (object)(ushort)small : null; } else { big = use_big ? big : (BigInteger)small; if (ty == typeof(int)) { clr = (big >= int.MinValue && big <= int.MaxValue) ? (object)(int)big : null; } else if (ty == typeof(uint)) { clr = (big >= uint.MinValue && big <= uint.MaxValue) ? (object)(uint)big : null; } else if (ty == typeof(long)) { clr = (big >= long.MinValue && big <= long.MaxValue) ? (object)(long)big : null; } else if (ty == typeof(ulong)) { clr = (big >= ulong.MinValue && big <= ulong.MaxValue) ? (object)(ulong)big : null; } else if (ty == typeof(float)) { clr = (object)(float)big; } else if (ty == typeof(double)) { clr = (object)(double)big; } else if (ty == typeof(decimal)) { clr = big.GetWords().Length <= 3 ? (object)(decimal)big : null; } else if (ty == typeof(object)) { clr = use_big ? null : (object)small; } else { clr = obj; } } } else if (obj.Does(Kernel.RealMO)) { // fractional value if (ty == typeof(decimal)) { // decimal is for people who care about exactness int rk; P6any n = Builtins.GetNumber(var, obj, out rk); BigInteger num, den; if (rk == Builtins.NR_FATRAT) { FatRat r = Kernel.UnboxAny <FatRat>(n); num = r.num; den = r.den; } else if (rk == Builtins.NR_FIXRAT) { Rat r = Kernel.UnboxAny <Rat>(n); num = r.num; den = r.den; } else if (rk == Builtins.NR_BIGINT) { num = Kernel.UnboxAny <BigInteger>(n); den = BigInteger.One; } else if (rk == Builtins.NR_FIXINT) { num = Kernel.UnboxAny <int>(n); den = BigInteger.One; } else { return(false); } BigInteger div, rem; int scale = 0; while (true) { div = BigInteger.DivRem(den, 10, out rem); if (rem.Sign != 0) { break; } den = div; scale++; } while (true) { div = BigInteger.DivRem(den, 5, out rem); if (rem.Sign != 0) { break; } den = div; num *= 2; scale++; } while (true) { div = BigInteger.DivRem(den, 2, out rem); if (rem.Sign != 0) { break; } den = div; num *= 5; scale++; } if (den != BigInteger.One) { return(false); } if (scale > 28) { return(false); } int[] bits = decimal.GetBits((decimal)num); bits[3] = scale << 16; clr = new decimal(bits); } else { double val = obj.mo.mro_raw_Numeric.Get(var); if (ty == typeof(float)) { clr = (object)(float)val; } else if (ty == typeof(double) || ty == typeof(object)) { clr = (object)val; } } } else if (obj.Does(Kernel.StrMO)) { string s = Kernel.UnboxAny <string>(obj); if (ty == typeof(char) && s.Length == 1) { clr = s[0]; } else if (ty == typeof(string)) { clr = s; } else if (ty == typeof(object)) { clr = s; } else { clr = obj; } } // "Callable" else if (typeof(Delegate).IsAssignableFrom(ty)) { MethodInfo needed = ty.GetMethod("Invoke"); ParameterInfo[] pi = needed.GetParameters(); if (pi.Length >= 10) { clr = null; } else if (needed.ReturnType != typeof(void)) { Type[] args = new Type[pi.Length + 1]; args[0] = needed.ReturnType; for (int i = 0; i < pi.Length; i++) { args[i + 1] = pi[i].ParameterType; } MethodInfo compat = delegate_methods[pi.Length * 2 + 1]. MakeGenericMethod(args); clr = Delegate.CreateDelegate(ty, obj, compat); } else { Type[] args = new Type[pi.Length]; for (int i = 0; i < pi.Length; i++) { args[i] = pi[i].ParameterType; } MethodInfo compat = delegate_methods[pi.Length * 2]; if (args.Length != 0) { compat = compat.MakeGenericMethod(args); } clr = Delegate.CreateDelegate(ty, obj, compat); } } else if (obj is BoxObject <object> ) { clr = Kernel.UnboxAny <object>(obj); } else { clr = obj; } return(clr != null && ty.IsAssignableFrom(clr.GetType())); }