public CodeExpression VisitLambda(Lambda l) { var e = new CodeLambdaExpression( l.args.Select(a => a.name.Accept(this)).ToArray(), l.body.Accept(this)); return(e); }
/// <summary> /// Rewrites the lambda expression. /// </summary> /// <param name="lambdaExpression">The lambda expression to rewrite.</param> /// <returns>Expression rewritten as code snippet</returns> private CodeSnippetExpression RewriteLambdaExpression(CodeLambdaExpression lambdaExpression) { using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture)) { if (lambdaExpression.Parameters.Count == 1 && lambdaExpression.Parameters[0].Type is CodeImplicitTypeReference) { sw.Write(this.generator.CreateEscapedIdentifier(lambdaExpression.Parameters[0].Name)); } else { sw.Write("("); string separator = string.Empty; foreach (CodeParameterDeclarationExpression cpde in lambdaExpression.Parameters) { sw.Write(separator); separator = ", "; if (!(cpde.Type is CodeImplicitTypeReference)) { this.generator.GenerateCodeFromExpression(cpde, sw, null); } else { sw.Write(this.generator.CreateEscapedIdentifier(cpde.Name)); } } sw.Write(")"); } sw.Write(" => "); bool didRewrite = false; if (lambdaExpression.BodyStatements.Count > 0) { sw.WriteLine(); this.WriteIndentation(sw); sw.WriteLine("{"); this.nestingLevel++; foreach (CodeStatement stat in lambdaExpression.BodyStatements) { this.WriteIndentation(sw); this.generator.GenerateCodeFromStatement(this.Rewrite(stat, ref didRewrite), sw, null); } this.nestingLevel--; this.WriteIndentation(sw); sw.Write("}"); didRewrite = true; } else { this.generator.GenerateCodeFromExpression(this.Rewrite(lambdaExpression.Body, ref didRewrite), sw, null); } return(new CodeSnippetExpression(sw.ToString())); } }
private CodeExpression RewriteLambdaExpression(CodeLambdaExpression lambdaExpression, ref bool didRewrite) { // This is a workaround for CodeDomTreeRewriter which does not handle CodeLambdaExpression in the case when // expressions further down the tree have been rewritten. (the lambda is rewritten as an empty CodeObject). var body = this.Rewrite(lambdaExpression.Body, ref didRewrite); if (didRewrite) { var parameters = lambdaExpression.Parameters.Cast <CodeParameterDeclarationExpression>().Select(e => e.Name).ToArray(); var result = new CodeLambdaExpression().WithParameters(parameters).WithBody(body); return(result); } return(lambdaExpression); }
/// <summary> /// Rewrites CodeExpression /// </summary> /// <param name="e">A CodeExpression to be rewritten.</param> /// <param name="didRewrite">A value which will be set to true if the rewriting returned a new object.</param> /// <returns>Rewritten CodeExpression.</returns> protected override CodeExpression Rewrite(CodeExpression e, ref bool didRewrite) { CodeLambdaExpression lambdaExpression = e as CodeLambdaExpression; if (lambdaExpression != null) { didRewrite = true; return(this.RewriteLambdaExpression(lambdaExpression)); } CodeQueryExpression queryExpression = e as CodeQueryExpression; if (queryExpression != null) { didRewrite = true; return(this.RewriteComprehensionExpression(queryExpression)); } CodeCreateAndInitializeObjectExpression objectCreateExpression = e as CodeCreateAndInitializeObjectExpression; if (objectCreateExpression != null) { didRewrite = true; return(this.RewriteCreateAndInitializeObjectExpression(objectCreateExpression)); } CodeArrayInitializerExpression arrayInitializer = e as CodeArrayInitializerExpression; if (arrayInitializer != null) { didRewrite = true; return(this.RewriteArrayInitializerExpression(arrayInitializer)); } CodeExclusiveOrExpression exclusiveOrExpression = e as CodeExclusiveOrExpression; if (exclusiveOrExpression != null) { didRewrite = true; return(this.RewriteExclusiveOrExpression(exclusiveOrExpression)); } CodeAsExpression asExpression = e as CodeAsExpression; if (asExpression != null) { didRewrite = true; return(this.RewriteAsExpression(asExpression)); } CodeIsExpression isExpression = e as CodeIsExpression; if (isExpression != null) { didRewrite = true; return(this.RewriteIsExpression(isExpression)); } CodePrimitiveExpression primitiveExpression = e as CodePrimitiveExpression; if (primitiveExpression != null) { return(this.RewritePrimitiveExpression(primitiveExpression, ref didRewrite)); } var ternaryExpression = e as CodeTernaryExpression; if (ternaryExpression != null) { didRewrite = true; return(this.RewriteTernaryExpression(ternaryExpression)); } var anonymousArray = e as CodeAnonymousArrayExpression; if (anonymousArray != null) { didRewrite = true; return(this.RewriteAnonymousArrayExpression(anonymousArray)); } return(base.Rewrite(e, ref didRewrite)); }
CodeExpression Translate_range(Application appl, CodeExpression[] args) { var argsCount = args.Length; if (1 <= argsCount && argsCount <= 3) { m.EnsureImport("System"); m.EnsureImport("System.Linq"); var enumerableRange = m.MethodRef(m.TypeRefExpr("Enumerable"), "Range"); var mathCeiling = m.MethodRef(m.TypeRefExpr("Math"), "Ceiling"); var convertToInt32 = m.MethodRef(m.TypeRefExpr("Convert"), "ToInt32"); var convertToDouble = m.MethodRef(m.TypeRefExpr("Convert"), "ToDouble"); switch (argsCount) { case 1: { // Enumerable.Range(0, count); var startExp = m.Prim(0); var countExp = args[0]; return(m.Appl(enumerableRange, startExp, countExp)); } case 2: { // Enumerable.Range(0, count); var startExp = args[0]; var stopExp = args[1]; var countExp = m.Sub(stopExp, startExp); return(m.Appl(enumerableRange, startExp, countExp)); } case 3: { // Enumerable.Range(0, count).Select(x => start + x * step); var startExp = args[0]; var stopExp = args[1]; var stepExp = args[2]; // count = (stop - start) divide_ceiling_by step; var rawCountExp = m.Sub(stopExp, startExp); var rawDoubleCountExp = m.Appl(convertToDouble, rawCountExp); var countDividedExp = m.Div(rawDoubleCountExp, stepExp); var countCeilingExp = m.Appl(mathCeiling, countDividedExp); var countExp = m.Appl(convertToInt32, countCeilingExp); // Enumerable.Range(0, count); var rangeExp = m.Appl(enumerableRange, m.Prim(0), countExp); // x => start + x * step; var lambdaArgExp = expTranslator.gensym.GenSymLocal("_x_", m.TypeRef("object")); var offsetExp = m.Mul(lambdaArgExp, stepExp); var positionExp = m.Add(startExp, offsetExp); var mapLambdaExp = new CodeLambdaExpression(new CodeExpression[] { lambdaArgExp }, positionExp); var selectExt = m.Access(rangeExp, "Select"); return(m.Appl(selectExt, mapLambdaExp)); } } } return(null); }
public void VisitLambda(CodeLambdaExpression l) { if (l.Arguments.Length == 1) { l.Arguments[0].Accept(this); } else { writer.Write("("); var sep = ""; foreach (var arg in l.Arguments) { writer.Write(sep); sep = ","; arg.Accept(this); } writer.Write(")"); } writer.Write(" =>"); if (l.Body != null) { writer.Write(" "); l.Body.Accept(this); } else { var sw = new CSharpStatementWriter(writer); sw.WriteStatements(l.Statements); } }
CodeExpression?Translate_isinstance(Application appl, CodeExpression[] args) { if (appl.args.Count != 2) { return(null); } List <Exp> types; if (appl.args[1].defval is PyTuple tuple) { types = tuple.values.ToList(); } else { types = new List <Exp> { appl.args[1].defval ! }; } var exp = appl.args[0].defval !.Accept(expTranslator); return(types. Select(t => m.BinOp( exp, CodeOperatorType.Is, m.TypeRefExpr(t.ToString()))) .Aggregate((a, b) => m.BinOp(a, CodeOperatorType.LogOr, b))); } CodeExpression Translate_int(Application appl, CodeExpression[] args) { m.EnsureImport("System"); var fn = m.MethodRef(m.TypeRefExpr("Convert"), "ToInt32"); return(m.Appl(fn, args)); } CodeExpression?Translate_list(Application appl, CodeExpression[] args) { if (args.Length == 0) { m.EnsureImport(TypeReferenceTranslator.GenericCollectionNamespace); return(m.New(m.TypeRef("List", "object"))); } if (args.Length == 1) { m.EnsureImport(TypeReferenceTranslator.LinqNamespace); var fn = m.MethodRef(args[0], "ToList"); return(m.Appl(fn)); } return(null); } CodeExpression?Translate_set(Application appl, CodeExpression[] args) { if (args.Length == 0 || args.Length == 1) { m.EnsureImport(TypeReferenceTranslator.GenericCollectionNamespace); return(m.New( m.TypeRef("HashSet", "object"), args)); } return(null); } CodeExpression?Translate_dict(Application appl, CodeExpression[] args) { if (args.Length == 0) { m.EnsureImport(TypeReferenceTranslator.GenericCollectionNamespace); return(m.New( m.TypeRef("Dictionary", "object", "object"))); } else if (args.All(a => a is CodeNamedArgument)) { m.EnsureImport(TypeReferenceTranslator.GenericCollectionNamespace); var exp = m.New( m.TypeRef("Dictionary", "string", "object")); exp.Initializer = new CodeCollectionInitializer( args.Cast <CodeNamedArgument>() .Select(a => new CodeCollectionInitializer( m.Prim( ((CodeVariableReferenceExpression)a.exp1).Name), a.exp2 !)) .ToArray()); return(exp); } else if (args.Length == 1) { m.EnsureImport(TypeReferenceTranslator.GenericCollectionNamespace); return(m.Appl(m.MethodRef(args[0], "ToDictionary"))); } return(null); } CodeExpression?Translate_len(Application appl, CodeExpression[] args) { if (args.Length == 1) { var arg = args[0]; //$TODO: if args is known to be an iterable, but not a collection, // using LinQ Count() instead? return(m.Access(arg, "Count")); } return(null); } CodeExpression?Translate_sum(Application appl, CodeExpression[] args) { if (args.Length == 1) { m.EnsureImport(TypeReferenceTranslator.LinqNamespace); var arg = args[0]; args = new CodeExpression[0]; var fn = m.Access(arg, "Sum"); return(m.Appl(fn, args)); } return(null); } CodeExpression?Translate_range(Application appl, CodeExpression[] args) { var argsCount = args.Length; if (1 <= argsCount && argsCount <= 3) { m.EnsureImport("System"); m.EnsureImport("System.Linq"); var enumerableRange = m.MethodRef(m.TypeRefExpr("Enumerable"), "Range"); var mathCeiling = m.MethodRef(m.TypeRefExpr("Math"), "Ceiling"); var convertToInt32 = m.MethodRef(m.TypeRefExpr("Convert"), "ToInt32"); var convertToDouble = m.MethodRef(m.TypeRefExpr("Convert"), "ToDouble"); switch (argsCount) { case 1: { // Enumerable.Range(0, count); var startExp = m.Prim(0); var countExp = args[0]; return(m.Appl(enumerableRange, startExp, countExp)); } case 2: { // Enumerable.Range(0, count); var startExp = args[0]; var stopExp = args[1]; var countExp = m.Sub(stopExp, startExp); return(m.Appl(enumerableRange, startExp, countExp)); } case 3: { // Enumerable.Range(0, count).Select(x => start + x * step); var startExp = args[0]; var stopExp = args[1]; var stepExp = args[2]; // count = (stop - start) divide_ceiling_by step; var rawCountExp = m.Sub(stopExp, startExp); var rawDoubleCountExp = m.Appl(convertToDouble, rawCountExp); var countDividedExp = m.Div(rawDoubleCountExp, stepExp); var countCeilingExp = m.Appl(mathCeiling, countDividedExp); var countExp = m.Appl(convertToInt32, countCeilingExp); // Enumerable.Range(0, count); var rangeExp = m.Appl(enumerableRange, m.Prim(0), countExp); // x => start + x * step; var lambdaArgExp = expTranslator.gensym.GenSymLocal("_x_", m.TypeRef("object")); var offsetExp = m.Mul(lambdaArgExp, stepExp); var positionExp = m.Add(startExp, offsetExp); var mapLambdaExp = new CodeLambdaExpression(new CodeExpression[] { lambdaArgExp }, positionExp); var selectExt = m.Access(rangeExp, "Select"); return(m.Appl(selectExt, mapLambdaExp)); } } } return(null); } CodeExpression?Translate_filter(Application appl, CodeExpression[] args) { if (args.Length == 2) { m.EnsureImport(TypeReferenceTranslator.GenericCollectionNamespace); m.EnsureImport(TypeReferenceTranslator.LinqNamespace); var filter = args[0]; if (appl.args[0].defval is NoneExp) { var formal = expTranslator.gensym.GenSymLocal("_p_", m.TypeRef("object")); filter = m.Lambda( new[] { formal }, m.BinOp(formal, CodeOperatorType.NotEqual, m.Prim(null))); } var fn = m.MethodRef( m.Appl(m.MethodRef(args[1], "Where"), filter), "ToList"); args = new CodeExpression[0]; return(m.Appl(fn, args)); } return(null); } CodeExpression?Translate_complex(Application appl, CodeExpression[] args) { if (args.Length == 2) { m.EnsureImport("System.Numerics"); return(m.New(m.TypeRef("Complex"), args)); } return(null); } CodeExpression?Translate_float(Application appl, CodeExpression[] args) { if (args[0] is CodePrimitiveExpression c && c.Value is Str str) { switch (str.s) { case "inf": case "+inf": case "Infinity": case "+Infinity": return(m.Access(m.TypeRefExpr("double"), "PositiveInfinity")); case "-inf": case "-Infinity": return(m.Access(m.TypeRefExpr("double"), "NegativeInfinity")); } } return(null); } CodeExpression Translate_sorted(Application appl, CodeExpression[] args) { if (args.Length == 0) { return(m.Appl(new CodeVariableReferenceExpression("sorted"), args)); } var iter = args[0]; var cmp = args.Length > 1 && !(args[1] is CodeNamedArgument) ? args[1] : null; var key = args.Length > 2 && !(args[2] is CodeNamedArgument) ? args[2] : null; var rev = args.Length > 3 && !(args[3] is CodeNamedArgument) ? args[3] : null; var namedArgs = args.OfType <CodeNamedArgument>().ToDictionary( k => ((CodeVariableReferenceExpression)k.exp1).Name, v => v.exp2); if (namedArgs.TryGetValue("cmp", out var tmp)) { cmp = tmp; } if (namedArgs.TryGetValue("key", out tmp)) { key = tmp; } if (namedArgs.TryGetValue("reverse", out tmp)) { rev = tmp; } m.EnsureImport(TypeReferenceTranslator.GenericCollectionNamespace); var formal = expTranslator.gensym.GenSymLocal("_p_", m.TypeRef("object")); return(m.ApplyMethod( m.ApplyMethod( iter, IsReverse(rev) ? "OrderByDescending" : "OrderBy", cmp ?? key ?? m.Lambda(new[] { formal }, formal)), "ToList")); } CodeExpression Translate_str(Application appl, CodeExpression[] args) { switch (args.Length) { case 1: return(m.ApplyMethod(args[0], "ToString")); case 2: case 3: //$TODO: careless about the third arg here. m.EnsureImport("System.Text"); var getEncoding = m.ApplyMethod( m.TypeRefExpr("Encoding"), "GetEncoding", args[1]); return(m.ApplyMethod(getEncoding, "GetString", args[0])); default: throw new NotImplementedException($"str({string.Join<CodeExpression>(",", args)})"); } }
/// <summary> /// Begins the new scope which will add statements to given lambda body. /// </summary> /// <param name="lambda">The lambda.</param> public abstract void BeginLambda(CodeLambdaExpression lambda);
/// <summary> /// Begins the new scope which will add statements to given lambda body. /// </summary> /// <param name="lambda">The lambda.</param> public override void BeginLambda(CodeLambdaExpression lambda) { this.blockStack.Push(this.currentBlock); this.currentBlock = new BlockInformation(null, BlockType.Lambda, lambda.BodyStatements, false); }