protected override void PostWalk(MethodCallExpression node) { base.PostWalk(node); var i = Unwrap(node.Instance); if (i != null && node.Method.Name == "Call" && i.Type.IsSubclassOf(typeof(Callable))) { var mi = i.Type.GetMethod("Invoke"); node.Method = mi; node.Instance = i; node.Arguments = node.Arguments.ConvertAll(e => Unwrap(e)); node.ParameterInfos = mi.GetParameters(); } }
protected override void PostWalk(MethodCallExpression node) { base.PostWalk(node); var i = Unwrap(node.Instance); if (i != null && node.Method.Name == "Call" && typeof(IronScheme.Runtime.Typed.ITypedCallable).IsAssignableFrom(i.Type)) { var mi = i.Type.GetMethod("Invoke"); node.Method = mi; node.Instance = i; node.Arguments = node.Arguments.ConvertAll(e => Unwrap(e)); node.ParameterInfos = mi.GetParameters(); } }
static bool IsSimpleCall(MethodCallExpression mce) { if (mce.Instance != null && !IsSimpleExpression(mce.Instance)) { return false; } foreach (var arg in mce.Arguments) { if (arg is MethodCallExpression) { MethodCallExpression imce = (MethodCallExpression)arg; if (!IsSimpleCall(imce)) { return false; } } if (!IsSimpleExpression(arg)) { return false; } } return true; }
// MethodCallExpression private void DefaultWalk(MethodCallExpression node) { if (Walk(node)) { WalkNode(node.Instance); IList<Expression> args = node.Arguments; if (args != null) { foreach (Expression e in args) { WalkNode(e); } } } PostWalk(node); }
bool IsTCE(MethodCallExpression mce, out Variable var) { var = null; // this could possibly removed if the label can be moved before the environment is allocated if (Current.HasEnvironment) return false; // i think this is to check if it is a return? //if (!mce.TailCall) return false; if (mce.Instance == null) return false; if (mce.Arguments.Count > 8) return false; var i = Unwrap(mce.Instance); if (i is CodeBlockExpression) { var cbe = i as CodeBlockExpression; if (cbe.Block == Current) { return true; } return false; } else { if (!typeof(Callable).IsAssignableFrom(i.Type)) return false; var be = i as BoundExpression; if (be == null) return false; var = be.Variable; if (/*!var.Lift ||*/ !typeof(Callable).IsAssignableFrom(var.Type) || var.ReAssigned) return false; if (!(mce.Method.Name == "Call" || mce.Method.Name == "Invoke")) return false; if (mce.Arguments.Count > 0 && mce.Arguments[0].Type == typeof(object[])) return false; var av = var.AssumedValue as MethodCallExpression; while (av == null && be.Variable.AssumedValue is BoundExpression) { be = be.Variable.AssumedValue as BoundExpression; av = be.Variable.AssumedValue as MethodCallExpression; } if (av == null && be.Variable.AssumedValue is NewExpression) { var ne = be.Variable.AssumedValue as NewExpression; if (!typeof(Callable).IsAssignableFrom(ne.Type)) return false; var cbe = ne.Arguments[0] as CodeBlockExpression; if (cbe == null || cbe.Block != Current) return false; } else { if (av == null || !typeof(Callable).IsAssignableFrom(av.Type) || av.Method.Name != "Create") return false; var cbe = av.Arguments[0] as CodeBlockExpression; if (cbe == null || cbe.Block != Current) return false; } return true; } }
bool IsHoistable(MethodCallExpression mce, out CodeBlockExpression cbe, out Variable var) { cbe = null; var = null; // Am I needed? //if (!mce.TailCall) return false; if (mce.Instance == null) return false; var i = Unwrap(mce.Instance); if (!typeof(Callable).IsAssignableFrom(i.Type)) return false; var be = i as BoundExpression; if (be == null) return false; var = be.Variable; int x; if (!refmap.TryGetValue(var, out x)) { return false; } else { if (x != 1) { return false; } } if (!callsites.TryGetValue(var, out x)) { return false; } else { if (x != 1) { return false; } } if (var.Lift || !typeof(Callable).IsAssignableFrom(var.Type) || var.ReAssigned) return false; if (!(mce.Method.Name == "Call" || mce.Method.Name == "Invoke")) return false; if (mce.Arguments.Count > 0 && mce.Arguments[0].Type == typeof(object[])) return false; if (mce.Arguments.Count > 8) return false; var av = var.AssumedValue as MethodCallExpression; while (av == null && be.Variable.AssumedValue is BoundExpression) { be = be.Variable.AssumedValue as BoundExpression; av = be.Variable.AssumedValue as MethodCallExpression; } if (av == null && be.Variable.AssumedValue is NewExpression) { var ne = be.Variable.AssumedValue as NewExpression; if (!typeof(Callable).IsAssignableFrom(ne.Type)) return false; cbe = ne.Arguments[0] as CodeBlockExpression; if (cbe == null || cbe.Block.Parent != Current) return false; } else { if (av == null || !typeof(Callable).IsAssignableFrom(av.Type) || av.Method.Name != "Create") return false; cbe = av.Arguments[0] as CodeBlockExpression; if (cbe == null || cbe.Block.Parent != Current) return false; } //if (av == null || av.Type != typeof(Callable) || av.Method.Name != "Create") return false; //cbe = av.Arguments[0] as CodeBlockExpression; //if (cbe == null || cbe.Block.Parent != Current) return false; //if (mce.Arguments.Count > 8) return false; return true; }
bool IsGood(MethodCallExpression mce, out Variable var) { var = null; // Am I needed? //if (!mce.TailCall) return false; if (mce.Instance == null) return false; var i = Unwrap(mce.Instance); if (!typeof(Callable).IsAssignableFrom(i.Type)) return false; var be = i as BoundExpression; if (be == null) return false; var = be.Variable; return true; }
protected override bool Walk(MethodCallExpression node) { var i = node.Instance; if (node.Method != Generator.ICallable_CallN) { while (i is UnaryExpression && i.NodeType == AstNodeType.Convert) { i = ((UnaryExpression)i).Operand; } if (i is BoundExpression) { var be = (BoundExpression)i; var v = be.Variable.Name; if (Builtins.IsTrue(Builtins.IsSymbolBound(v))) { var val = Builtins.SymbolValue(v); var c = val as BuiltinMethod; if (c != null) { var mb = c.Binder; var pars = new Expression[node.Arguments.Count]; node.Arguments.CopyTo(pars, 0); Type[] types = Array.ConvertAll(pars, x => x.Type); MethodCandidate mc = mb.MakeBindingTarget(CallType.None, types); if (mc != null) { var meth = mc.Target.Method as MethodInfo; node.Method = meth; node.Instance = null; } } else if (val is Closure) { var cc = val as Closure; // will not work on varargs, need to somehow decorate them var meth = Array.Find(cc.Targets, x => x.GetParameters().Length == node.Arguments.Count && (Generator.AllowTransientBinding || !Generator.IsTransient(x.Module))); if (meth != null) { node.Method = meth; node.Instance = null; } else { meth = Array.Find(cc.VarargTargets, x => x.GetParameters().Length - 1 <= node.Arguments.Count && (Generator.AllowTransientBinding || !Generator.IsTransient(x.Module))); if (meth != null) { var newargs = new List<Expression>(); var pars = meth.GetParameters(); var parlen = pars.Length; int x = 0; for (; x < parlen - 1; x++) { newargs.Add(node.Arguments[x]); } var tail = new List<Expression>(); for (; x < node.Arguments.Count; x++) { tail.Add(node.Arguments[x]); } var tailarr = tail.ToArray(); newargs.Add(Ast.ComplexCallHelper(Compiler.Generator.MakeList(tailarr, true), tailarr)); node.Arguments.Clear(); node.Arguments.AddRange(newargs); node.Method = meth; node.ParameterInfos = pars; node.Instance = null; } } } } } } return base.Walk(node); }