public GTTree(IEnumerable<Value> list) : this() { var v = new GTTree(); foreach (Value ex in list) v = (GTTree)v.Add(ex); // fake mutator this.Value = v.Value; this.Left = v.Left; this.Right = v.Right; }
public Value Evaluate(Scope scope) { // Evaluate the function Value v = Function.Evaluate(scope); Value ret = new GTTree(); int c = v.Count; foreach (var res in v.Enumerate()) { var r = res.Self(); if (r.Type != GTType.Function) if (c == 1) throw new InvalidOperationException("Cannot call non-function type"); else continue; GTFunction f = (GTFunction)res; // Check the parameter count if (Parameters.Count > f.Parameters.Count) if (c == 1) throw new InvalidOperationException("Too many arguments in call to function: " + Function.ToString()); else continue; // Create evaluation context Scope s = new Scope(f.Container); // Add this() for recursion s.Add("this", f); for (int i = 0; i < Parameters.Count; i++) s.Add(f.Parameters[i], Parameters[i].Evaluate(scope)); // All parameters filled if (Parameters.Count == f.Parameters.Count) { Value o; if (f.Body == null) { // Invoke the method var w = (WrapperFunc)f; o = (Value)w.Method.Invoke(null, (from par in w.Parameters select new Usage(par).Evaluate(s)).ToArray()); } else o = f.Body.Evaluate(s); ret = ret.Add(o); continue; } // No partial application in list context if (c > 1) continue; // Partial application: Create a new function var newparams = new List<string>(); for (int i = f.Parameters.Count - Parameters.Count; i < f.Parameters.Count; i++) newparams.Add(f.Parameters[i]); return new GTFunction(f.Body, s, newparams); } if (ret.Count == 1) return ret[0]; // single values -> skip the list stuff else return ret; }