internal GState(Compartment setting, string orig, P6any actions) { this.setting = setting; this.actions = (actions == setting.AnyP) ? null : actions; orig_s = orig; orig_a = orig.ToCharArray(); highwater = (orig_a.Length < 100 || !Cursor.HwTrace) ? int.MaxValue : 0; }
public static bool obj_can(P6any obj, string mname) { return obj.mo.mro_methods.ContainsKey(mname); }
// Better, but still fudgy. Relies too much on path structure. public static void cb_init_slave(Variable cb, P6any cmd_obj_dir, Variable unit, Variable staticSub, Variable type, Variable param, Variable value) { if (Downcaller.responder != null) return; Downcaller.UnitP = unit.Fetch(); Downcaller.StaticSubP = staticSub.Fetch(); Downcaller.TypeP = type.Fetch(); Downcaller.ParamP = param.Fetch(); Downcaller.ValueP = value.Fetch(); string[] obj_dirs = !cmd_obj_dir.IsDefined() ? new string[0] : cmd_obj_dir.Isa(cmd_obj_dir.mo.setting.StrMO) ? new string[] { cmd_obj_dir.mo.mro_raw_Str.Get(cmd_obj_dir) } : Builtins.UnboxLoS(Kernel.NewRWListVar(cmd_obj_dir)) ; if (obj_dirs.Length == 0) { obj_dirs = new string[2]; obj_dirs[0] = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.Combine("..", "obj")); obj_dirs[1] = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "NieczaModuleCache"); } for (int i = 0; i < obj_dirs.Length; i++) { Directory.CreateDirectory(obj_dirs[i]); // mkdir -p obj_dirs[i] = Path.GetFullPath(obj_dirs[i]); } Downcaller.obj_dirs = obj_dirs; Downcaller.upcall_cb = cb; Downcaller.responder = (IDictionary) new Niecza.CLRBackend.DowncallReceiver(); }
public static Variable HandleSpecial3(Variable av0, Variable av1, Variable av2, P6any ao0, P6any ao1, P6any ao2, Func<Variable,Variable,Variable,Variable> dgt) { uint jrank = uint.MaxValue; int jpivot = -1; CheckSpecialArg(0, ref jpivot, ref jrank, ao0); CheckSpecialArg(1, ref jpivot, ref jrank, ao1); CheckSpecialArg(2, ref jpivot, ref jrank, ao2); if (jpivot < 0) return dgt(av0, av1, av2); Variable[] avs = new Variable[] { av0, av1, av2 }; return AutoThread(avs[jpivot].Fetch(), delegate(Variable n) { avs[jpivot] = n; return dgt(avs[0], avs[1], avs[2]); }); }
public static int get_count(P6any fcni) { if (!fcni.Isa(Kernel.CodeMO)) return 1; // can't introspect fake subs (?) return get_count((SubInfo) fcni.GetSlot("info")); }
public static Variable count(P6any fcni) { int i = get_count(fcni); return (i == int.MaxValue) ? MakeFloat(double.PositiveInfinity) : MakeInt(i); }
// This function implements the actual looping part of autothreading public static Variable AutoThread(P6any j, Func<Variable,Variable> dgt) { P6opaque j_ = (P6opaque)j; P6any listObj = (P6any) j_.slots[1]; Variable[] list = Kernel.UnboxAny<Variable[]>(listObj); Variable[] nlist = new Variable[list.Length]; for (int i = 0; i < list.Length; i++) { nlist[i] = dgt(list[i]); } P6any newList = Kernel.BoxRaw(nlist, Kernel.ParcelMO); P6opaque newJunc = new P6opaque(Kernel.JunctionMO); newJunc.slots[0] = j_.slots[0]; newJunc.slots[1] = newList; return Kernel.NewROScalar(newJunc); }
public static Variable arity(P6any fcni) { if (!fcni.Isa(Kernel.CodeMO)) return MakeInt(1); // can't introspect fake subs (?) SubInfo si = (SubInfo) fcni.GetSlot("info"); if (si.sig == null) return MakeInt(1); int arity = 0; foreach (Parameter p in si.sig.parms) { int fl = p.flags; if ((fl & (Parameter.SLURPY_CAP | Parameter.SLURPY_POS | Parameter.SLURPY_PCL | Parameter.SLURPY_NAM | Parameter.OPTIONAL | Parameter.DEFOUTER | Parameter.HASDEFAULT)) != 0) continue; if ((fl & Parameter.POSITIONAL) == 0) continue; arity++; } return MakeInt(arity); }
// If a number is <= NR_FLOAT, return it as if at NR_FLOAT public static double PromoteToFloat(int rank, P6any vret) { Rat r; FatRat fr; if (!vret.IsDefined()) return 0; switch (rank) { case NR_FIXINT: return Kernel.UnboxAny<int>(vret); case NR_BIGINT: return (double)Kernel.UnboxAny<BigInteger>(vret); case NR_FIXRAT: r = Kernel.UnboxAny<Rat>(vret); return (double)r.num / (double)r.den; case NR_FATRAT: fr = Kernel.UnboxAny<FatRat>(vret); return (double)fr.num / (double)fr.den; case NR_FLOAT: default: return Kernel.UnboxAny<double>(vret); } }
// If a number is <= NR_FIXRAT, return it as if at NR_FIXRAT public static Rat PromoteToFixRat(int rank, P6any vret) { if (!vret.IsDefined()) return new Rat(BigInteger.Zero, 1); switch (rank) { case NR_FIXINT: return new Rat(Kernel.UnboxAny<int>(vret), 1); case NR_BIGINT: return new Rat(Kernel.UnboxAny<BigInteger>(vret), 1); case NR_FIXRAT: default: return Kernel.UnboxAny<Rat>(vret); } }
public override void Store(P6any v) { string str = backing.Fetch().mo.mro_raw_Str.Get(backing); int left = (from < 0) ? 0 : (from > str.Length) ? str.Length : from; int right = ((length > (str.Length - left)) ? (str.Length - left) : (length < 0) ? 0 : length) + left; string lfr = str.Substring(0, left); string mfr = v.mo.mro_raw_Str.Get(Kernel.NewROScalar(v)); string rfr = str.Substring(right); backing.Store(Kernel.BoxRaw<string>(lfr + mfr + rfr, Kernel.StrMO)); }
// If a number is <= NR_FIXINT, return it as if at NR_FIXINT public static int PromoteToFixInt(int rank, P6any vret) { if (!vret.IsDefined()) return 0; return Kernel.UnboxAny<int>(vret); }
// If a number is <= NR_FATRAT, return it as if at NR_FATRAT public static FatRat PromoteToFatRat(int rank, P6any vret) { Rat r; if (!vret.IsDefined()) return new FatRat(BigInteger.Zero,BigInteger.One); switch (rank) { case NR_FIXINT: return new FatRat(Kernel.UnboxAny<int>(vret), BigInteger.One); case NR_BIGINT: return new FatRat(Kernel.UnboxAny<BigInteger>(vret), BigInteger.One); case NR_FIXRAT: r = Kernel.UnboxAny<Rat>(vret); return new FatRat(r.num, r.den); case NR_FATRAT: default: return Kernel.UnboxAny<FatRat>(vret); } }
// If a number is <= NR_COMPLEX, return it as if at NR_COMPLEX public static Complex PromoteToComplex(int rank, P6any vret) { Rat r; FatRat fr; if (!vret.IsDefined()) return new Complex(0,0); switch (rank) { case NR_FIXINT: return new Complex(Kernel.UnboxAny<int>(vret), 0); case NR_BIGINT: return new Complex((double)Kernel.UnboxAny<BigInteger>(vret), 0); case NR_FIXRAT: r = Kernel.UnboxAny<Rat>(vret); return new Complex((double)r.num / (double)r.den, 0); case NR_FATRAT: fr = Kernel.UnboxAny<FatRat>(vret); return new Complex((double)fr.num / (double)fr.den, 0); case NR_FLOAT: return new Complex(Kernel.UnboxAny<double>(vret), 0); case NR_COMPLEX: default: return Kernel.UnboxAny<Complex>(vret); } }
// If a number is <= NR_BIGINT, return it as if at NR_BIGINT public static BigInteger PromoteToBigInt(int rank, P6any vret) { if (!vret.IsDefined()) return BigInteger.Zero; switch (rank) { case NR_FIXINT: return Kernel.UnboxAny<int>(vret); case NR_BIGINT: default: return Kernel.UnboxAny<BigInteger>(vret); } }
public static P6any who(P6any obj) { return obj.mo.who; }
// Type-check val against any, tracking state appropriately for // junctions. static void CheckSpecialArg(int ix, ref int pivot, ref uint rank, P6any val) { if (val.mo.is_any) { // fine as is } else if (val.mo.HasMRO(Kernel.JunctionMO)) { int jtype = Kernel.UnboxAny<int>((P6any)(val as P6opaque).slots[0]) / 2; if ((uint)jtype < rank) { rank = (uint)jtype; pivot = ix; } } else { throw new NieczaException("Nominal type check failed for #" + ix + " needed Any got " + val.mo.name); } }
public static Variable pstash_at_key(P6any st, string key) { return Kernel.UnboxAny<StashCursor>(st).Raw(key, null); }
// Assign a value to a variable, while handling list variables sensibly public static void AssignV(Variable lhs, P6any rhs) { if (!lhs.islist) { lhs.Store(rhs); } else { lhs.Fetch().mo.mro_LISTSTORE.Get(lhs, Kernel.NewROScalar(rhs)); } }
public static Variable pstash_bind_key(P6any st, string key, Variable to) { return Kernel.UnboxAny<StashCursor>(st).Raw(key, to); }
public static Frame CallNext(Frame th, P6any cap) { Frame to = th; while (to != null && to.curDisp == null) to = to.caller; if (to == null || to.curDisp.next == null) return Kernel.Die(th, "No next function to call!"); DispatchEnt de = to.curDisp.next; P6opaque o = cap as P6opaque; Variable[] p = to.pos; VarHash n = to.named; if (o != null) { p = (Variable[]) o.slots[0]; n = o.slots[1] as VarHash; } return de.info.Binder(th, de.outer, de.ip6, p, n, false, de); }
public static Thread start_p6_thread(P6any sub) { Frame th = Kernel.GetTopFrame(); th.MarkSharedChain(); Thread thr = new Thread(delegate () { Kernel.SetupThreadParent(th); Kernel.RunInferior(sub.Invoke(Kernel.GetInferiorRoot(), Variable.None, null)); }); thr.Start(); return thr; }
// Coerce a value to numeric and return the group code public static P6any GetNumber(Variable v, P6any o, out int rank) { if (o.mo.num_rank >= 0) { rank = o.mo.num_rank; } else { o = o.mo.mro_Numeric.Get(v).Fetch(); rank = o.mo.num_rank; if (rank < 0) throw new NieczaException("Not a valid primitive number " + o.mo.name); } if (rank == NR_FIXINT && o is BoxObject<BigInteger>) rank = NR_BIGINT; return o; }
public static Variable stash_at_key(P6any st, string key) { return Kernel.GetVar(Kernel.UnboxAny<string>(st), key).v; }
// These three functions implement type checking and junctional // autothreading for signatures like (Any, Any). // // You need to pass a reference to the function in so that these may // call it for autothreading. public static Variable HandleSpecial1(Variable av0, P6any ao0, Func<Variable,Variable> dgt) { uint jrank = uint.MaxValue; int jpivot = -1; CheckSpecialArg(0, ref jpivot, ref jrank, ao0); if (jpivot < 0) return dgt(av0); return AutoThread(ao0, dgt); }
public static Variable stash_bind_key(P6any st, string key, Variable to) { Kernel.GetVar(Kernel.UnboxAny<string>(st), key).Bind(to); return to; }
public override void Store(P6any v) { }
public static Variable stash_delete_key(P6any st, string key) { string lkey = Kernel.UnboxAny<string>(st); lkey = (char)lkey.Length + lkey + key; StashEnt r; if (!Kernel.currentGlobals.TryGetValue(lkey, out r)) return Kernel.AnyMO.typeVar; Kernel.currentGlobals.Remove(key); return r.v; }
public static Variable cb_cached_but(P6any but, Variable v1, Variable v2) { P6any a1 = v1.Fetch(); P6any a2 = v2.Fetch(); Dictionary<P6any,Variable> subcache; if (!role_cache.TryGetValue(a1, out subcache)) role_cache[a1] = subcache = new Dictionary<P6any,Variable>(); Variable var; if (subcache.TryGetValue(a2, out var)) return var; // Mega-Hack - stop lots of internal data from being retained by // CALLER pointers Kernel.SetTopFrame(null); var = Builtins.InvokeSub(but, v1, v2); return subcache[a2] = var; }
public static Variable stash_exists_key(P6any st, string key) { string lkey = Kernel.UnboxAny<string>(st); lkey = (char)lkey.Length + lkey + key; return Kernel.currentGlobals.ContainsKey(lkey) ? Kernel.TrueV : Kernel.FalseV; }