private Expression GenCall(Call ph, Expression prev) { Contract.Requires <ArgumentNullException>(ph != null); if (ph is MapCall) { return(GenMapCall((MapCall)ph, prev)); } // 関数あるいは,Globalを入れるために,0番目を開けた状態で,引数配列を作る。 var sfxs = ph.Arguments.Select(a => a.Suffix).ToArray(); var args = new List <Expression> { null }; // index : 0 if (prev != null) { args.Add(prev); } args.AddRange(ph.Arguments.Select(a => ElemGen.GenElem(a.Argument))); var callInfo = new CallInfo(sfxs.Length + (prev == null ? 0 : 1), sfxs); args[0] = ElemGen.GenElemCore(ph.Target); DynamicMetaObjectBinder binder; if (ph.Target.ElementType == ElementType.Symbol && !(args[0] is ParameterExpression)) { binder = Factory.InvokeMemberBinder(((Symbol)ph.Target).Name, callInfo); args[0] = Global; } else { binder = Factory.InvokeBinder(callInfo); } return(Expression.Dynamic(binder, typeof(object), args)); }
private Expression GenMapCall(MapCall ph, Expression prev) { Contract.Requires <ArgumentNullException>(ph != null); if (ph.FirstArg == null && prev == null) { throw Error("「それぞれ」の対象が指定されていません。", ph.Range.Start); } if (ph.FirstArg != null && prev != null) { throw Error("「それぞれ」の対象が二重に指定されています。", ph.Range.Start); } var value = prev ?? ElemGen.GenElem(ph.FirstArg.Argument); Expression lambda; { var param = Expression.Parameter(typeof(object), "要素"); var args = new List <Expression> { ElemGen.GenElemCore(ph.Target), param }; var sfxs = new List <string>(); if (ph.FirstArg != null) { sfxs.Add(ph.FirstArg.Suffix); } foreach (var pair in ph.Arguments) { args.Add(ElemGen.GenElem(pair.Argument)); sfxs.Add(pair.Suffix); } var callInfo = new CallInfo(args.Count - 1, sfxs); DynamicMetaObjectBinder binder; if (ph.Target.ElementType == ElementType.Symbol && !(args[0] is ParameterExpression)) { binder = Factory.InvokeMemberBinder(((Symbol)ph.Target).Name, callInfo); args[0] = Global; } else { binder = Factory.InvokeBinder(callInfo); } lambda = Expression.Lambda(Expression.Dynamic(binder, typeof(object), args), "それぞれ", new[] { param }); } return(Expression.Dynamic(Factory.MapBinder, typeof(object), lambda, value)); }