protected virtual void __eval_internal_recursive(FSharpList<FScheme.Value> args, Dictionary<PortData, FScheme.Value> outPuts, int level = 0) { var argSets = new List<FSharpList<FScheme.Value>>(); //create a zip of the incoming args and the port data //to be used for type comparison var portComparison = args.Zip(InPortData, (first, second) => new Tuple<Type, Type>(first.GetType(), second.PortType)) .ToList(); var listOfListComparison = args.Zip(InPortData, (first, second) => new Tuple<bool, Type>(Utils.IsListOfLists(first), second.PortType)); //there are more than zero arguments //and there is either an argument which does not match its expections //OR an argument which requires a list and gets a list of lists //AND argument lacing is not disabled if (ArgumentLacing != LacingStrategy.Disabled && args.Any() && (portComparison.Any(x => x.Item1 == typeof (Value.List) && x.Item2 != typeof (Value.List)) || listOfListComparison.Any(x => x.Item1 && x.Item2 == typeof (Value.List)))) { //if the argument is of the expected type, then //leave it alone otherwise, wrap it in a list int j = 0; foreach (var arg in args) { //incoming value is list and expecting single if (portComparison.ElementAt(j).Item1 == typeof (Value.List) && portComparison.ElementAt(j).Item2 != typeof (Value.List)) { //leave as list argSets.Add(((Value.List) arg).Item); } //incoming value is list and expecting list else { //check if we have a list of lists, if so, then don't wrap argSets.Add( Utils.IsListOfLists(arg) && !AcceptsListOfLists(arg) ? ((Value.List) arg).Item : Utils.MakeFSharpList(arg)); } j++; } IEnumerable<IEnumerable<Value>> lacedArgs = null; switch (ArgumentLacing) { case LacingStrategy.First: lacedArgs = argSets.SingleSet(); break; case LacingStrategy.Shortest: lacedArgs = argSets.ShortestSet(); break; case LacingStrategy.Longest: lacedArgs = argSets.LongestSet(); break; case LacingStrategy.CrossProduct: lacedArgs = argSets.CartesianProduct(); break; } var evalResult = OutPortData.ToDictionary( x => x, _ => FSharpList<Value>.Empty); var evalDict = new Dictionary<PortData, Value>(); //run the evaluate method for each set of //arguments in the lace result. foreach (var argList in lacedArgs) { evalDict.Clear(); var thisArgsAsFSharpList = Utils.ToFSharpList(argList); var portComparisonLaced = thisArgsAsFSharpList.Zip(InPortData, (first, second) => new Tuple<Type, Type>(first.GetType(), second.PortType)).ToList(); int jj = 0; bool bHasListNotExpecting = false; foreach (var argLaced in argList) { //incoming value is list and expecting single if (ArgumentLacing != LacingStrategy.Disabled && thisArgsAsFSharpList.Any() && portComparisonLaced.ElementAt(jj).Item1 == typeof (Value.List) && portComparison.ElementAt(jj).Item2 != typeof (Value.List) && (!AcceptsListOfLists(argLaced) || !Utils.IsListOfLists(argLaced)) ) { bHasListNotExpecting = true; break; } jj++; } if (bHasListNotExpecting) { if (level > 20) throw new Exception("Too deep recursive list containment by lists, only 21 are allowed"); Dictionary<PortData, FScheme.Value> outPutsLevelPlusOne = new Dictionary<PortData, FScheme.Value>(); __eval_internal_recursive(Utils.ToFSharpList(argList), outPutsLevelPlusOne, level + 1); //pack result back foreach (var dataLaced in outPutsLevelPlusOne) { var dataL = dataLaced.Key; var valueL = outPutsLevelPlusOne[dataL]; evalResult[dataL] = FSharpList<Value>.Cons(valueL, evalResult[dataL]); } continue; } else Evaluate(Utils.ToFSharpList(argList), evalDict); OnEvaluate(); foreach (var data in OutPortData) { evalResult[data] = FSharpList<Value>.Cons(evalDict[data], evalResult[data]); } } //the result of evaluation will be a list. we split that result //and send the results to the outputs foreach (var data in OutPortData) { var portResults = evalResult[data]; //if the lacing is cross product, the results //need to be split back out into a set of lists //equal in dimension to the first list argument if (args[0].IsList && ArgumentLacing == LacingStrategy.CrossProduct) { var length = portResults.Count(); var innerLength = length/((Value.List) args[0]).Item.Count(); int subCount = 0; var listOfLists = FSharpList<Value>.Empty; var innerList = FSharpList<Value>.Empty; for (int i = 0; i < length; i++) { innerList = FSharpList<Value>.Cons(portResults.ElementAt(i), innerList); subCount++; if (subCount == innerLength) { subCount = 0; listOfLists = FSharpList<Value>.Cons(Value.NewList(innerList), listOfLists); innerList = FSharpList<Value>.Empty; } } evalResult[data] = Utils.ToFSharpList(listOfLists); } else { //Reverse the evaluation results so they come out right way around evalResult[data] = Utils.ToFSharpList(evalResult[data].Reverse()); } outPuts[data] = Value.NewList(evalResult[data]); } } else { Evaluate(args, outPuts); OnEvaluate(); } }
public override void Evaluate(FSharpList<Value> args, Dictionary<PortData, Value> outPuts) { //if this element maintains a collcection of references //then clear the collection if (this is IClearable) (this as IClearable).ClearReferences(); List<FSharpList<Value>> argSets = new List<FSharpList<Value>>(); //create a zip of the incoming args and the port data //to be used for type comparison var portComparison = args.Zip(InPortData, (first, second) => new Tuple<Type, Type>(first.GetType(), second.PortType)); //if any value is a list whose expectation is a single //do an auto map //TODO: figure out a better way to do this than using a lot //of specific excludes if (args.Count() > 0 && portComparison.Any(x => x.Item1 == typeof(Value.List) && x.Item2 != typeof(Value.List)) && !(this.ArgumentLacing == LacingStrategy.Disabled)) { //if the argument is of the expected type, then //leave it alone otherwise, wrap it in a list int j = 0; foreach (var arg in args) { //incoming value is list and expecting single if (portComparison.ElementAt(j).Item1 == typeof(Value.List) && portComparison.ElementAt(j).Item2 != typeof(Value.List)) { //leave as list argSets.Add(((Value.List)arg).Item); } //incoming value is list and expecting list else { //wrap in list argSets.Add(Utils.MakeFSharpList(arg)); } j++; } IEnumerable<IEnumerable<Value>> lacedArgs = null; switch (this.ArgumentLacing) { case LacingStrategy.First: lacedArgs = argSets.SingleSet(); break; case LacingStrategy.Shortest: lacedArgs = argSets.ShortestSet(); break; case LacingStrategy.Longest: lacedArgs = argSets.LongestSet(); break; case LacingStrategy.CrossProduct: lacedArgs = argSets.CartesianProduct(); break; } //setup a list to hold the results //each output will have its own results collection List<FSharpList<Value>> results = new List<FSharpList<FScheme.Value>>(); for(int i=0; i<OutPortData.Count(); i++) { results.Add(FSharpList<Value>.Empty); } //FSharpList<Value> result = FSharpList<Value>.Empty; //run the evaluate method for each set of //arguments in the la result. do these //in reverse order so our cons comes out the right //way around for (int i = lacedArgs.Count() - 1; i >= 0; i--) { var evalResult = Evaluate(Utils.MakeFSharpList(lacedArgs.ElementAt(i).ToArray())); //if the list does not have the same number of items //as the number of output ports, then throw a wobbly if (!evalResult.IsList) throw new Exception("Output value of the node is not a list."); for (int k = 0; k < OutPortData.Count(); k++) { FSharpList<Value> lst = ((Value.List)evalResult).Item; results[k] = FSharpList<Value>.Cons(lst[k], results[k]); } runCount++; } //the result of evaluation will be a list. we split that result //and send the results to the outputs for (int i = 0; i < OutPortData.Count(); i++) { outPuts[OutPortData[i]] = Value.NewList(results[i]); } } else { Value evalResult = Evaluate(args); runCount++; if (!evalResult.IsList) throw new Exception("Output value of the node is not a list."); FSharpList<Value> lst = ((Value.List)evalResult).Item; //the result of evaluation will be a list. we split that result //and send the results to the outputs for (int i = 0; i < OutPortData.Count(); i++) { outPuts[OutPortData[i]] = lst[i]; } } ValidateConnections(); }
public override void Evaluate(FSharpList<Value> args, Dictionary<PortData, Value> outPuts) { //THE OLD WAY //outPuts[OutPortData[0]] = Evaluate(args); //THE NEW WAY //if this element maintains a collcection of references //then clear the collection if (this is IClearable) (this as IClearable).ClearReferences(); List<FSharpList<Value>> argSets = new List<FSharpList<Value>>(); //create a zip of the incoming args and the port data //to be used for type comparison var portComparison = args.Zip(InPortData, (first, second) => new Tuple<Type, Type>(first.GetType(), second.PortType)); //if any value is a list whose expectation is a single //do an auto map //TODO: figure out a better way to do this than using a lot //of specific excludes if (args.Count() > 0 && portComparison.Any(x => x.Item1 == typeof(Value.List) && x.Item2 != typeof(Value.List)) && !(this.ArgumentLacing == LacingStrategy.Disabled)) { //if the argument is of the expected type, then //leave it alone otherwise, wrap it in a list int j = 0; foreach (var arg in args) { //incoming value is list and expecting single if (portComparison.ElementAt(j).Item1 == typeof(Value.List) && portComparison.ElementAt(j).Item2 != typeof(Value.List)) { //leave as list argSets.Add(((Value.List)arg).Item); } //incoming value is list and expecting list else { //wrap in list argSets.Add(Utils.MakeFSharpList(arg)); } j++; } IEnumerable<IEnumerable<Value>> lacedArgs = null; switch (this.ArgumentLacing) { case LacingStrategy.First: lacedArgs = argSets.SingleSet(); break; case LacingStrategy.Shortest: lacedArgs = argSets.ShortestSet(); break; case LacingStrategy.Longest: lacedArgs = argSets.LongestSet(); break; case LacingStrategy.CrossProduct: lacedArgs = argSets.CartesianProduct(); break; } //setup an empty list to hold results FSharpList<Value> result = FSharpList<Value>.Empty; //run the evaluate method for each set of //arguments in the cartesian result. do these //in reverse order so our cons comes out the right //way around for (int i = lacedArgs.Count() - 1; i >= 0; i--) { var evalResult = Evaluate(Utils.MakeFSharpList(lacedArgs.ElementAt(i).ToArray())); result = FSharpList<Value>.Cons(evalResult, result); runCount++; } outPuts[OutPortData[0]] = Value.NewList(result); } else { outPuts[OutPortData[0]] = Evaluate(args); runCount++; } }
public override void Evaluate(FSharpList<Value> args, Dictionary<PortData, Value> outPuts) { //if this element maintains a collcection of references //then clear the collection if(this is IClearable) (this as IClearable).ClearReferences(); List<FSharpList<Value>> argSets = new List<FSharpList<Value>>(); //create a zip of the incoming args and the port data //to be used for type comparison var portComparison = args.Zip(InPortData, (first, second) => new Tuple<Type, Type>(first.GetType(), second.PortType)); var listOfListComparison = args.Zip(InPortData, (first, second) => new Tuple<bool, Type>(Utils.IsListOfLists(first), second.PortType)); //there are more than zero arguments //and there is either an argument which does not match its expections //OR an argument which requires a list and gets a list of lists //AND argument lacing is not disabled if (args.Count() > 0 && (portComparison.Any(x => x.Item1 == typeof(Value.List) && x.Item2 != typeof(Value.List)) || listOfListComparison.Any(x => x.Item1 == true && x.Item2 == typeof(Value.List))) && this.ArgumentLacing != LacingStrategy.Disabled) { //if the argument is of the expected type, then //leave it alone otherwise, wrap it in a list int j = 0; foreach (var arg in args) { //incoming value is list and expecting single if (portComparison.ElementAt(j).Item1 == typeof (Value.List) && portComparison.ElementAt(j).Item2 != typeof (Value.List)) { //leave as list argSets.Add(((Value.List)arg).Item); } //incoming value is list and expecting list else { //check if we have a list of lists, if so, then don't wrap if (Utils.IsListOfLists(arg)) //leave as list argSets.Add(((Value.List)arg).Item); else //wrap in list argSets.Add(Utils.MakeFSharpList(arg)); } j++; } IEnumerable<IEnumerable<Value>> lacedArgs = null; switch (this.ArgumentLacing) { case LacingStrategy.First: lacedArgs = argSets.SingleSet(); break; case LacingStrategy.Shortest: lacedArgs = argSets.ShortestSet(); break; case LacingStrategy.Longest: lacedArgs = argSets.LongestSet(); break; case LacingStrategy.CrossProduct: lacedArgs = argSets.CartesianProduct(); break; } //setup an empty list to hold results FSharpList<Value> result = FSharpList<Value>.Empty; //run the evaluate method for each set of //arguments in the cartesian result. do these //in reverse order so our cons comes out the right //way around for (int i = lacedArgs.Count() - 1; i >= 0; i--) { var evalResult = Evaluate(Utils.MakeFSharpList(lacedArgs.ElementAt(i).ToArray())); result = FSharpList<Value>.Cons(evalResult, result); } outPuts[OutPortData[0]] = Value.NewList(result); } else { outPuts[OutPortData[0]] = Evaluate(args); } ValidateConnections(); if (dynSettings.Controller.UIDispatcher != null && this is IDrawable) { dynSettings.Controller.UIDispatcher.Invoke(new Action(() => (this as IDrawable).Draw())); } }