// CodeBlockExpression private void DefaultWalk(CodeBlockExpression node) { if (node.IsDeclarative && Walk(node)) { WalkNode(node.Block); } PostWalk(node); }
protected internal override void PostWalk(CodeBlockExpression node) { // We use PostWalk here since Walk is only called for IsDeclarative=true // Currently, CodeBlockExpression ignores the DelegateType. This will result in the generation of // an incorrectly type delegate. For eg, for event hookup with a source code snippet, a language might // generate a rule that creates CodeBlockExpressions with the source code snippet typed as EventHandler. // The interpreter will ignore that a create a CallWithContextN delegate, which will cause a problem // with the event hookup if (node.DelegateType != null) { _hasUnsupportedNodes = true; } }
// CodeBlockExpression private void Dump(CodeBlockExpression node) { int id = Enqueue(node.Block); Out(String.Format(".block ({0} #{1}", node.Block.Name, id)); Indent(); bool nl = false; if (node.ForceWrapperMethod) { nl = true; Out(Flow.NewLine, "ForceWrapper"); } if (node.IsStronglyTyped) { nl = true; Out(Flow.NewLine, "StronglyTyped"); } if (node.IsDeclarative) { nl = true; Out(Flow.NewLine, "Declarative"); } Dedent(); Out(nl ? Flow.NewLine : Flow.None, ")"); }
protected internal static Expression InlineCall(CodeBlock parent, CodeBlockExpression cbe, bool istailpostion, params Expression[] pp) { // all var names are unique. CodeBlock cb = cbe.Block; if (parent.IsGlobal) { return CallNormal(cbe, pp); } List<Statement> assigns = new List<Statement>(); int i = 0; cb.Inlined = true; if (parent.Filename == null && cb.Filename != null) { parent.Filename = cb.Filename; } var parentvars = new List<Variable>(parent.Variables); foreach (Variable p in cb.Parameters) { SymbolId origname = p.Name; p.Name = (SymbolId)Builtins.GenSym(p.Name); p.Block = parent; p.Kind = Variable.VariableKind.Local; parent.AddVariable(p); Expression val = Unwrap(pp[i]); if (val.Type != typeof(SymbolId) && !Generator.assigns.ContainsKey(origname)) { if (p.Type == typeof(object)) { p.Type = val.Type; assigns.Add(Ast.Write(p, val)); } else { assigns.Add(Ast.Write(p, Ast.ConvertHelper(val, p.Type))); } } else { if (p.Type == typeof(object)) { assigns.Add(Ast.Write(p, pp[i])); } else { assigns.Add(Ast.Write(p, Ast.ConvertHelper(pp[i], p.Type))); } } if (p.Lift) { parent.HasEnvironment = true; } i++; } foreach (Variable l in cb.Variables) { if (l.DefaultValue == null && l.Kind != Variable.VariableKind.Global) { l.Name = (SymbolId)Builtins.GenSym(l.Name); } l.Block = parent; parent.AddVariable(l); if (l.Lift) { parent.HasEnvironment = true; } } Expression body = RewriteReturn(cb.Body); if (assigns.Count > 0) { return Ast.Comma(Ast.Void(Ast.Block(assigns)), body); } else { return body; } }
protected static Expression InlineCall(CodeBlock parent, CodeBlockExpression cbe, params Expression[] pp) { return InlineCall(parent, cbe, false, pp); }
protected static Expression CallVarArgs(CodeBlockExpression cbe, Expression[] ppp) { bool needscontext = NeedsContext(cbe); //true; int pc = cbe.Block.ParameterCount; Expression[] tail = new Expression[ppp.Length - (pc - 1)]; Array.Copy(ppp, ppp.Length - tail.Length, tail, 0, tail.Length); Expression[] nppp = new Expression[pc]; Array.Copy(ppp, nppp, ppp.Length - tail.Length); if (tail.Length > 0) { nppp[nppp.Length - 1] = Ast.ComplexCallHelper(MakeList(tail, true), tail); } else { nppp[nppp.Length - 1] = Ast.Null(); } ppp = nppp; MethodInfo dc = GetDirectCallable(needscontext, pc, cbe.Type); if (needscontext) { ppp = ArrayUtils.Insert<Expression>(Ast.CodeContext(), ppp); } cbe = Ast.CodeBlockReference(cbe.Block, CallTargets.GetTargetType(needscontext, pc, false)); cbe.Block.Bind(); var r = Ast.ComplexCallHelper(cbe, dc, ppp); if (SpanHint.IsValid) { r.SetLoc(SpanHint); } return r; }
static bool NeedsContext(CodeBlockExpression cbe) { return cbe.Block.IsClosure || cbe.Block.ExplicitCodeContextExpression == null && (cbe.Block.Parent != null && !cbe.Block.Parent.IsGlobal); }
protected static Expression CallNormal(CodeBlockExpression cbe, params Expression[] ppp) { bool needscontext = NeedsContext(cbe); // true; int pc = ppp.Length; MethodInfo dc = GetDirectCallable(needscontext, pc, cbe.Type); List<Variable> paruninit = new List<Variable>(cbe.Block.Parameters); for (int i = 0; i < ppp.Length; i++) { if (ppp[i].Type == typeof(Uninitialized)) { paruninit[i].SetUnInitialized(); } } if (needscontext) { ppp = ArrayUtils.Insert<Expression>(Ast.CodeContext(), ppp); } var delegatetype = cbe.Type != typeof(Delegate) ? cbe.Type : CallTargets.GetTargetType(needscontext, pc, false); cbe = Ast.CodeBlockReference(cbe.Block, delegatetype); cbe.Block.Bind(); var r = Ast.ComplexCallHelper(cbe, dc, ppp); if (SpanHint.IsValid) { r.SetLoc(SpanHint); } return r; }
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); } }
// CodeBlockExpression interrupt flow analysis protected internal override bool Walk(CodeBlockExpression node) { return false; }
// CodeBlockExpression interrupt flow analysis protected internal override bool Walk(CodeBlockExpression node) { return(false); }
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; }
static Expression InlineCall(CodeBlock parent, CodeBlockExpression cbe, params Expression[] pp) { // all var names are unique. CodeBlock cb = cbe.Block; List<Statement> assigns = new List<Statement>(); int i = 0; cb.Inlined = true; var parentvars = new List<Variable>(parent.Variables); foreach (Variable p in cb.Parameters) { SymbolId origname = p.Name; p.Name = (SymbolId)Builtins.GenSym(p.Name); p.Block = parent; p.Kind = Variable.VariableKind.Local; parent.AddVariable(p); assigns.Add(Ast.Write(p, pp[i])); if (p.Lift) { parent.HasEnvironment = true; } i++; } foreach (Variable l in cb.Variables) { if (l.DefaultValue == null && l.Kind != Variable.VariableKind.Global) { l.Name = (SymbolId)Builtins.GenSym(l.Name); } l.Block = parent; parent.AddVariable(l); if (l.Lift) { parent.HasEnvironment = true; } } assigns.Add(cb.Body); return Ast.Void(Ast.Block(assigns)); }
// CodeBlockExpression private Expression Rewrite(CodeBlockExpression node) { // No action necessary return(node); }