public override void Emit(CodeGen cg) { // TODO: Improve the following to direct call: Callable.Call(Callable.Create(...)) //EmitLocation(cg); if (_instance != null && !cg.IsDynamicMethod) // damn DM! // go away! // this dangerous too for now { if (!IsParamsMethod()) { if (_instance is CodeBlockExpression) { CodeBlockExpression cbe = (CodeBlockExpression)_instance; Debug.Assert(_arguments.Count == _parameterInfos.Length); for (int arg = 0; arg < _parameterInfos.Length; arg++) { Expression argument = _arguments[arg]; Type type = _parameterInfos[arg].ParameterType; EmitArgument(cg, argument, type); } EmitLocation(cg); if (tailcall) { // TODO: Remove tail calls from list of known non-recursive methods //Console.WriteLine(cbe.Block.Name); tailcall = true; } cbe.EmitDirect(cg, tailcall); if (ScriptDomainManager.Options.LightweightDebugging && !tailcall && Span.IsValid) { cg.EmitConstant(SpanToLong(Span)); cg.EmitCall(Debugging.DebugMethods.ExpressionOut); } return; } } else // 'params' { } } if (_method == BuiltinsIsTrue) { EmitLocation(cg); var arg = Unwrap(_arguments[0]); if (arg.Type == typeof(bool)) { arg.Emit(cg); } else if (arg.Type == typeof(object)) { Label next = cg.DefineLabel(); Label end = cg.DefineLabel(); arg.Emit(cg); cg.Emit(OpCodes.Dup); cg.Emit(OpCodes.Isinst, typeof(bool)); cg.Emit(OpCodes.Brfalse, next); cg.EmitUnbox(typeof(bool)); cg.Emit(OpCodes.Br, end); cg.MarkLabel(next); cg.Emit(OpCodes.Pop); cg.EmitConstant(true); cg.MarkLabel(end); } else { cg.EmitConstant(true); } return; } var ii = _instance; ii = Unwrap(ii); BoundExpression.Emitter fixup = null; bool varargs = false; var pttt = Array.ConvertAll(_parameterInfos, x => x.ParameterType); if (ii is BoundExpression) { var be = ii as BoundExpression; if (BoundExpression.Fixups.ContainsKey(be.Variable.Name)) { fixup = BoundExpression.Fixups[be.Variable.Name]; pttt = BoundExpression.FixupTypes[be.Variable.Name]; } else { CodeGen rcg; CodeGenDescriptor[] cgd; if (CodeGen._codeBlockLookup.TryGetValue(be.Variable.Name, out rcg)) { var lpttt = pt.GetValue(rcg.MethodInfo) as Type[]; if (_arguments.Count == lpttt.Length) { _method = rcg.MethodInfo; pttt = lpttt; } } else if (CodeGen._codeBlockLookupX.TryGetValue(be.Variable.Name, out rcg)) { var lpppt = pt.GetValue(rcg.MethodInfo) as Type[]; if (lpppt.Length - 1 > _arguments.Count) { } else if (AllArgsAreObject(_arguments)) { _method = rcg.MethodInfo; pttt = lpppt; varargs = true; } else if (_arguments.Count == 1 && lpppt.Length == 1 && _arguments[0].Type == typeof(object[]) && _arguments[0] is MethodCallExpression && ((MethodCallExpression)_arguments[0])._method.Name == "ListToVector") { _arguments[0] = Unwrap(((MethodCallExpression)_arguments[0]).Arguments[0]); _method = rcg.MethodInfo; pttt = lpppt; } } else if (CodeGen._codeBlockLookupN.TryGetValue(be.Variable.Name, out cgd)) { if (AllArgsAreObject(_arguments)) { foreach (var i in cgd) { if (i.arity == _arguments.Count) { _method = i.cg.MethodInfo; pttt = pt.GetValue(_method) as Type[]; break; } } } } } } // Emit instance, if calling an instance method if (!_method.IsStatic) { Type type = _method.DeclaringType; if (type.IsValueType) { _instance.EmitAddress(cg, type); } else { if (fixup == null) { _instance.Emit(cg); } } } if (varargs) { int arg = 0; for (; arg < pttt.Length - 1; arg++) { Expression argument = _arguments[arg]; Type type = pttt[arg]; EmitArgument(cg, argument, type); } // make tail var tailargs = new List <Expression>(); for (; arg < _arguments.Count; arg++) { tailargs.Add(_arguments[arg]); } var tailarr = tailargs.ToArray(); var tail = Ast.ComplexCallHelper(MakeList(tailarr, true), tailarr); EmitArgument(cg, tail, typeof(object)); } else { // Emit arguments // we cant really complain here or show error... Debug.Assert(_arguments.Count == pttt.Length); for (int arg = 0; arg < pttt.Length && arg < _arguments.Count; arg++) { Expression argument = _arguments[arg]; Type type = pttt[arg]; EmitArgument(cg, argument, type); } } // check for possible conversion/boxing needed, disabled tail call if (tailcall) { if (ShouldTailCallBeRemoved(cg)) { //Console.WriteLine("Removing tail call: {0} in {1}", cg.MethodBase, cg.TypeGen.AssemblyGen.AssemblyBuilder); tailcall = false; } } EmitLocation(cg); // Emit the actual call if (fixup == null) { cg.EmitCall(_method, tailcall); } else { fixup(cg, tailcall); } if (ScriptDomainManager.Options.LightweightDebugging && !tailcall && Span.IsValid) { cg.EmitConstant(SpanToLong(Span)); cg.EmitCall(Debugging.DebugMethods.ExpressionOut); } }