public static PValue RunStatically(StackContext sctx, PValue[] args) { if (args == null) throw new ArgumentNullException("args"); if (sctx == null) throw new ArgumentNullException("sctx"); var xss = new List<IEnumerable<PValue>>(); foreach (var arg in args) { var xs = Map._ToEnumerable(sctx, arg); if (xs != null) xss.Add(xs); } var n = xss.Count; if (n < 2) throw new PrexoniteException("Except requires at least two sources."); var t = new Dictionary<PValue, bool>(); //All elements of the last source are considered candidates foreach (var x in xss[n - 1]) if (!t.ContainsKey(x)) t.Add(x, true); for (var i = 0; i < n - 1; i++) foreach (var x in xss[i]) if (t.ContainsKey(x)) t.Remove(x); return sctx.CreateNativePValue(t.Keys); }
/// <summary> /// Sorts an IEnumerable. /// <code>function sort(ref f1(a,b), ref f2(a,b), ... , xs) /// { ... }</code> /// </summary> /// <param name = "sctx">The stack context in which the sort is performed.</param> /// <param name = "args">A list of sort expressions followed by the list to sort.</param> /// <returns>The a sorted copy of the list.</returns> public override PValue Run(StackContext sctx, PValue[] args) { if (sctx == null) throw new ArgumentNullException("sctx"); if (args == null) args = new PValue[] {}; var lst = new List<PValue>(); if (args.Length == 0) return PType.Null.CreatePValue(); else if (args.Length == 1) { var set = Map._ToEnumerable(sctx, args[0]); foreach (var x in set) lst.Add(x); return (PValue) lst; } else { var clauses = new List<PValue>(); for (var i = 0; i + 1 < args.Length; i++) clauses.Add(args[i]); foreach (var x in Map._ToEnumerable(sctx, args[args.Length - 1])) lst.Add(x); lst.Sort( delegate(PValue a, PValue b) { foreach (var f in clauses) { var pdec = f.IndirectCall(sctx, new[] {a, b}); if (!(pdec.Type is IntPType)) pdec = pdec.ConvertTo(sctx, PType.Int); var dec = (int) pdec.Value; if (dec != 0) return dec; } return 0; }); return (PValue) lst; } }
protected override IEnumerable<PValue> CoroutineRun(ContextCarrier sctxCarrier, PValue[] args) { if (args == null) throw new ArgumentNullException("args"); if (sctxCarrier == null) throw new ArgumentNullException("sctxCarrier"); var sctx = sctxCarrier.StackContext; var xss = new List<IEnumerable<PValue>>(); foreach (var arg in args) { var xs = Map._ToEnumerable(sctx, arg); if (xs != null) xss.Add(xs); } var n = xss.Count; if (n < 2) throw new PrexoniteException("Intersect requires at least two sources."); var t = new Dictionary<PValue, int>(); //All elements of the first source are considered candidates foreach (var x in xss[0]) if (!t.ContainsKey(x)) t.Add(x, 1); var d = new Dictionary<PValue, object>(); for (var i = 1; i < n - 1; i++) { foreach (var x in xss[i]) if ((!d.ContainsKey(x)) && t.ContainsKey(x)) { d.Add(x, null); //only current source t[x]++; } d.Clear(); } foreach (var x in xss[n - 1]) if ((!d.ContainsKey(x)) && t.ContainsKey(x)) { d.Add(x, null); //only current source var k = t[x] + 1; if (k == n) yield return x; } }
protected override IEnumerable<PValue> CoroutineRun(ContextCarrier sctxCarrier, PValue[] args) { if (args == null) throw new ArgumentNullException("args"); if (sctxCarrier == null) throw new ArgumentNullException("sctxCarrier"); if (args.Length < 1) throw new PrexoniteException("GroupBy requires at least one argument."); var f = args[0]; var sctx = sctxCarrier.StackContext; var groups = new Dictionary<PValue, List<PValue>>(); for (var i = 1; i < args.Length; i++) { var arg = args[i]; var xs = Map._ToEnumerable(sctx, arg); if (xs == null) continue; foreach (var x in xs) { var fx = f.IndirectCall(sctx, new[] {x}); if (!groups.ContainsKey(fx)) { var lst = new List<PValue>(); lst.Add(x); groups.Add(fx, lst); } else { groups[fx].Add(x); } } } // DO NO CONVERT TO LINQ, dereferencing of sctx MUST be delayed! // ReSharper disable LoopCanBeConvertedToQuery foreach (var pair in groups) { yield return new PValueKeyValuePair(pair.Key, (PValue) pair.Value); } // ReSharper restore LoopCanBeConvertedToQuery }
/// <summary> /// Creates a new Prexonite virtual machine. /// </summary> public Engine() { //Thread local storage for stack _stackSlot = Thread.AllocateDataSlot(); //Metatable _meta = MetaTable.Create(); //PTypes _pTypeMap = new Dictionary<Type, PType>(); _ptypemapiterator = new PTypeMapIterator(this); //int PTypeMap[typeof (int)] = PType.Int; PTypeMap[typeof (long)] = PType.Int; PTypeMap[typeof (short)] = PType.Int; PTypeMap[typeof (byte)] = PType.Int; #if UseNonCTSIntegers PTypeMap[typeof(uint)] = IntPType.Instance; PTypeMap[typeof(ulong)] = IntPType.Instance; PTypeMap[typeof(ushort)] = IntPType.Instance; PTypeMap[typeof(sbyte)] = IntPType.Instance; #endif //char PTypeMap[typeof (char)] = PType.Char; //bool PTypeMap[typeof (bool)] = PType.Bool; //real PTypeMap[typeof (float)] = PType.Real; PTypeMap[typeof (double)] = PType.Real; //string PTypeMap[typeof (string)] = PType.String; PTypeMap[typeof (List<PValue>)] = PType.List; PTypeMap[typeof (PValue[])] = PType.List; PTypeMap[typeof (PValueHashtable)] = PType.Hash; //Registry _pTypeRegistry = new SymbolTable<Type>(); _pTypeRegistryIterator = new PTypeRegistryIterator(this); PTypeRegistry[IntPType.Literal] = typeof (IntPType); PTypeRegistry[BoolPType.Literal] = typeof (BoolPType); PTypeRegistry[RealPType.Literal] = typeof (RealPType); PTypeRegistry[CharPType.Literal] = typeof (CharPType); PTypeRegistry[StringPType.Literal] = typeof (StringPType); PTypeRegistry[NullPType.Literal] = typeof (NullPType); PTypeRegistry[ObjectPType.Literal] = typeof (ObjectPType); PTypeRegistry[ListPType.Literal] = typeof (ListPType); PTypeRegistry[StructurePType.Literal] = typeof (StructurePType); PTypeRegistry[HashPType.Literal] = typeof (HashPType); PTypeRegistry[StructurePType.Literal] = typeof (StructurePType); //Assembly registry _registeredAssemblies = new List<Assembly>(); foreach ( var assName in Assembly.GetExecutingAssembly().GetReferencedAssemblies()) _registeredAssemblies.Add(Assembly.Load(assName.FullName)); //Commands _commandTable = new CommandTable(); PCommand cmd; Commands.AddEngineCommand(PrintAlias, ConsolePrint.Instance); Commands.AddEngineCommand(PrintLineAlias, ConsolePrintLine.Instance); Commands.AddEngineCommand(MetaAlias, Prexonite.Commands.Core.Meta.Instance); Commands.AddEngineCommand(BoxedAlias, Boxed.Instance); // The concatenate command has been renamed to `string_concat` for Prexonite 2 Commands.AddEngineCommand(ConcatenateAlias, Concat.Instance); Commands.AddEngineCommand(OldConcatenateAlias, Concat.Instance); Commands.AddEngineCommand(MapAlias, cmd = Map.Instance); Commands.AddEngineCommand(SelectAlias, cmd); Commands.AddEngineCommand(FoldLAlias, FoldL.Instance); Commands.AddEngineCommand(FoldRAlias, FoldR.Instance); Commands.AddEngineCommand(DisposeAlias, Dispose.Instance); // There is a macro that uses the same alias (CallAlias) // it has the same purpose. For backwards compatibility, // the command table will retain the old binding. Commands.AddEngineCommand(CallAlias, Call.Instance); Commands.AddEngineCommand(Call.Alias, Call.Instance); Commands.AddEngineCommand(ThunkAlias, ThunkCommand.Instance); Commands.AddEngineCommand(AsThunkAlias, AsThunkCommand.Instance); Commands.AddEngineCommand(ForceAlias, ForceCommand.Instance); Commands.AddEngineCommand(ToSeqAlias, ToSeqCommand.Instance); // There is a macro that uses the same alias (Call_MemberAlias) // it has the same purpose. For backwards compatibility, // the command table will retain the old binding. Commands.AddEngineCommand(Call_MemberAlias, Call_Member.Instance); Commands.AddEngineCommand(Call_Member.Alias, Call_Member.Instance); Commands.AddEngineCommand(CallerAlias, Caller.Instance); Commands.AddEngineCommand(PairAlias, Pair.Instance); Commands.AddEngineCommand(UnbindAlias, Unbind.Instance); Commands.AddEngineCommand(SortAlias, Sort.Instance); Commands.AddEngineCommand(SortAlternativeAlias, Sort.Instance); Commands.AddEngineCommand(LoadAssemblyAlias, LoadAssembly.Instance); Commands.AddEngineCommand(DebugAlias, new Debug()); Commands.AddEngineCommand(SetCenterAlias, SetCenterCommand.Instance); Commands.AddEngineCommand(SetLeftAlias, SetLeftCommand.Instance); Commands.AddEngineCommand(SetRightAlias, SetRightCommand.Instance); Commands.AddEngineCommand(AllAlias, All.Instance); Commands.AddEngineCommand(WhereAlias, Where.Instance); Commands.AddEngineCommand(SkipAlias, Skip.Instance); Commands.AddEngineCommand(LimitAlias, cmd = Limit.Instance); Commands.AddEngineCommand(TakeAlias, cmd); Commands.AddEngineCommand(AbsAlias, Abs.Instance); Commands.AddEngineCommand(CeilingAlias, Ceiling.Instance); Commands.AddEngineCommand(ExpAlias, Exp.Instance); Commands.AddEngineCommand(FloorAlias, Floor.Instance); Commands.AddEngineCommand(LogAlias, Log.Instance); Commands.AddEngineCommand(MaxAlias, Max.Instance); Commands.AddEngineCommand(MinAlias, Min.Instance); Commands.AddEngineCommand(PiAlias, Pi.Instance); Commands.AddEngineCommand(RoundAlias, Round.Instance); Commands.AddEngineCommand(SinAlias, Sin.Instance); Commands.AddEngineCommand(CosAlias, Cos.Instance); Commands.AddEngineCommand(SqrtAlias, Sqrt.Instance); Commands.AddEngineCommand(TanAlias, Tan.Instance); Commands.AddEngineCommand(CharAlias, Char.Instance); Commands.AddEngineCommand(CountAlias, Count.Instance); Commands.AddEngineCommand(DistinctAlias, cmd = new Distinct()); Commands.AddEngineCommand(UnionAlias, cmd); Commands.AddEngineCommand(UniqueAlias, cmd); Commands.AddEngineCommand(FrequencyAlias, new Frequency()); Commands.AddEngineCommand(GroupByAlias, new GroupBy()); Commands.AddEngineCommand(IntersectAlias, new Intersect()); // There is a macro that uses the same alias (Call_TailAlias) // it has the same purpose. For backwards compatibility, // the command table will retain the old binding. Commands.AddEngineCommand(Call_TailAlias, Call_Tail.Instance); Commands.AddEngineCommand(Call_Tail.Alias, Call_Tail.Instance); Commands.AddEngineCommand(ListAlias, List.Instance); Commands.AddEngineCommand(EachAlias, Each.Instance); Commands.AddEngineCommand(ExistsAlias, new Exists()); Commands.AddEngineCommand(ForAllAlias, new ForAll()); Commands.AddEngineCommand(CompileToCilAlias, CompileToCil.Instance); Commands.AddEngineCommand(TakeWhileAlias, TakeWhile.Instance); Commands.AddEngineCommand(ExceptAlias, Except.Instance); Commands.AddEngineCommand(RangeAlias, Range.Instance); Commands.AddEngineCommand(ReverseAlias, Reverse.Instance); Commands.AddEngineCommand(HeadTailAlias, HeadTail.Instance); Commands.AddEngineCommand(AppendAlias, Append.Instance); Commands.AddEngineCommand(SumAlias, Sum.Instance); Commands.AddEngineCommand(Contains.Alias, Contains.Instance); Commands.AddEngineCommand(ChanAlias, Chan.Instance); Commands.AddEngineCommand(SelectAlias, Select.Instance); Commands.AddEngineCommand(Call_AsyncAlias, CallAsync.Instance); Commands.AddEngineCommand(CallAsync.Alias, CallAsync.Instance); Commands.AddEngineCommand(AsyncSeqAlias, AsyncSeq.Instance); Commands.AddEngineCommand(CallSubPerformAlias, CallSubPerform.Instance); Commands.AddEngineCommand(PartialCallAlias, new PartialCallCommand()); Commands.AddEngineCommand(PartialMemberCallAlias, PartialMemberCallCommand.Instance); Commands.AddEngineCommand(PartialConstructionAlias, PartialConstructionCommand.Instance); Commands.AddEngineCommand(PartialTypeCheckAlias, PartialTypeCheckCommand.Instance); Commands.AddEngineCommand(PartialTypeCastAlias, PartialTypecastCommand.Instance); Commands.AddEngineCommand(PartialStaticCallAlias, PartialStaticCallCommand.Instance); Commands.AddEngineCommand(FunctionalPartialCallCommand.Alias, FunctionalPartialCallCommand.Instance); Commands.AddEngineCommand(FlippedFunctionalPartialCallCommand.Alias, FlippedFunctionalPartialCallCommand.Instance); Commands.AddEngineCommand(PartialCallStarImplCommand.Alias, PartialCallStarImplCommand.Instance); Commands.AddEngineCommand(ThenAlias, ThenCommand.Instance); Commands.AddEngineCommand(Id.Alias, Id.Instance); Commands.AddEngineCommand(Const.Alias, Const.Instance); OperatorCommands.AddToEngine(this); Commands.AddEngineCommand(CreateEnumerator.Alias, CreateEnumerator.Instance); Commands.AddEngineCommand(CreateModuleName.Alias, CreateModuleName.Instance); Commands.AddEngineCommand(GetUnscopedAstFactory.Alias, GetUnscopedAstFactory.Instance); Commands.AddEngineCommand(CreateSourcePosition.Alias, CreateSourcePosition.Instance); Commands.AddEngineCommand(SeqConcat.Alias, SeqConcat.Instance); }
/// <summary> /// Takes an argument list and injects elements of top-level lists into that argument list. /// </summary> /// <param name = "sctx">The stack context in which to convert enumerables.</param> /// <param name = "args">The raw list of arguments to process.</param> /// <param name = "offset">The offset at which to start processing.</param> /// <returns>A copy of the argument list with top-level lists expanded.</returns> public static List<PValue> FlattenArguments(StackContext sctx, PValue[] args, int offset) { if (args == null) args = new PValue[] {}; var iargs = new List<PValue>(); for (var i = offset; i < args.Length; i++) { var arg = args[i]; var folded = Map._ToEnumerable(sctx, arg); if (folded == null) iargs.Add(arg); else iargs.AddRange(folded); } return iargs; }
public static PValue RunStatically(StackContext sctx, PValue[] args) { if (sctx == null) throw new ArgumentNullException("sctx"); if (args == null) throw new ArgumentNullException("args"); //Get f IIndirectCall f; if (args.Length < 1) throw new PrexoniteException("The foldl command requires a function argument."); else f = args[0]; //Get left PValue left; if (args.Length < 2) left = null; else left = args[1]; //Get the source IEnumerable<PValue> source; if (args.Length == 3) { var psource = args[2]; source = Map._ToEnumerable(sctx, psource) ?? new[] {psource}; } else { var lstsource = new List<PValue>(); for (var i = 1; i < args.Length; i++) { var multiple = Map._ToEnumerable(sctx, args[i]); if (multiple != null) lstsource.AddRange(multiple); else lstsource.Add(args[i]); } source = lstsource; } return Run(sctx, f, left, source); }
protected static IEnumerable<PValue> CoroutineRunStatically(ContextCarrier sctxCarrier, PValue[] args) { if (sctxCarrier == null) throw new ArgumentNullException("sctxCarrier"); if (args == null) throw new ArgumentNullException("args"); var sctx = sctxCarrier.StackContext; //Get f IIndirectCall f; if (args.Length < 1) f = null; else f = args[0]; //Get the source IEnumerable<PValue> source; if (args.Length == 2) { var psource = args[1]; source = _ToEnumerable(sctx, psource) ?? new[] {psource}; } else { var lstsource = new List<PValue>(); for (var i = 1; i < args.Length; i++) { var multiple = _ToEnumerable(sctx, args[i]); if (multiple != null) lstsource.AddRange(multiple); else lstsource.Add(args[i]); } source = lstsource; } //Note: need to forward element because this method must remain lazy. foreach (var value in CoroutineRun(sctxCarrier, f, source)) { yield return value; } }
/// <summary> /// Implementation of (obj, id, arg1, arg2, arg3, ..., argn) => obj.id(arg1, arg2, arg3, ..., argn); /// </summary> /// <param name = "sctx">The stack context in which to call the member of <paramref name = "obj" />.</param> /// <param name = "obj">The obj to call.</param> /// <param name = "isSet">Indicates whether to perform a Set-call.</param> /// <param name = "id">The id of the member to call.</param> /// <param name = "args">The array of arguments to pass to the member call.<br /> /// Lists and coroutines are expanded.</param> /// <returns>The result returned by the member call.</returns> /// <exception cref = "ArgumentNullException"><paramref name = "sctx" /> is null.</exception> public PValue Run(StackContext sctx, PValue obj, bool isSet, string id, params PValue[] args) { if (obj == null) return PType.Null.CreatePValue(); if (sctx == null) throw new ArgumentNullException("sctx"); if (args == null) args = new PValue[] {}; var iargs = new List<PValue>(); for (var i = 0; i < args.Length; i++) { var arg = args[i]; var folded = Map._ToEnumerable(sctx, arg); if (folded == null) iargs.Add(arg); else iargs.AddRange(folded); } return obj.DynamicCall(sctx, iargs.ToArray(), isSet ? PCall.Set : PCall.Get, id); }