private static Expression GetUnaryAST(ParseNode @operator, ParseNode target, Expression context) { //NOTE:unary expressions are unchainable without grouping return(Expression.Dynamic(DLRUtil.GetUnaryBinder(@operator.Token.Type), typeof(object), target.GetAST(context))); }
private static Expression GetCompareAST(IList <ParseNode> nodes, int start, Expression context, Expression chain = null) { //Rewrite chained compare expressions to chained AND expressions, e.g. 5>4>3> --> 5>4 AND 4>3 Debug.Assert(nodes.Count >= 3 && nodes.Count % 2 == 1); Expression result; if (start == 0) { result = chain; } else { var link = Expression.Dynamic(DLRUtil.GetBinaryBinder(nodes[start - 1].Token.Type), typeof(object), nodes[start - 2].GetAST(context), nodes[start].GetAST(context)); chain = chain != null ? Expression.Dynamic(DLRUtil.GetBinaryBinder(TokenType.AND), typeof(object), link, chain) : link; result = GetCompareAST(nodes, start - 2, context, chain); } return(result); }
private static Expression GetBinaryAST(IList <ParseNode> nodes, int start, Expression context) { //chain from left to right //2 + 3 + 4 is calculated as (2+3)+4, 15%12%5 as (15%12)%5 Debug.Assert(nodes.Count >= 3 && nodes.Count % 2 == 1); return(start == 0 ? nodes[start].GetAST(context) : Expression.Dynamic(DLRUtil.GetBinaryBinder(nodes[start - 1].Token.Type), typeof(object), GetBinaryAST(nodes, start - 2, context), nodes[start].GetAST(context))); }
private static CallSiteBinder GetFunctionCallBinder(IList <ParseNode> nodes, int argCount, bool isStatic) { var funcText = nodes[0].Token.Text; Debug.Assert(funcText.Length >= 2 && funcText.EndsWith("(")); var funcName = funcText.Substring(0, funcText.Length - 1); if (isStatic) { funcName = funcName.ToUpperInvariant(); } return(DLRUtil.GetFunctionCallBinder(funcName, argCount, isStatic)); }
private static Expression GetPowerAST(IList <ParseNode> nodes, int start, Expression context) { //Have to rewrite power expressions to Math.Pow function calls because C# runtime does not support the ^ operator like VB //a^b^c is rewritten as Math.Pow(Math.Pow(a, b), c) and calculated as (a^b)^c Debug.Assert(nodes.Count >= 3 && nodes.Count % 2 == 1); return(start == 0 ? nodes[start].GetAST(context) : Expression.Dynamic(DLRUtil.GetFunctionCallBinder("Pow", 2), typeof(object), Expression.Constant(typeof(Math)), GetPowerAST(nodes, start - 2, context), nodes[start].GetAST(context))); }
private static Expression GetMemberExpression(IList <ParseNode> nodes, int start, Expression context) { Debug.Assert(nodes.Count >= 3 && nodes.Count % 2 == 1); Expression result; if (start == 0) { result = GetInnerAST(nodes, context); } else { var @operator = nodes[start - 1].Token; var baseExpr = GetMemberExpression(nodes, start - 2, context); if (@operator.Type == TokenType.DOT) { var child = nodes[start].Nodes[0]; if (child.Token.Type == TokenType.FunctionCall) { result = GetFunctionAST(child.Nodes, baseExpr, false, context); } else if (child.Token.Type == TokenType.IDENTIFIER) { var fieldName = nodes[start].Nodes[0].Token.Text; result = Expression.Dynamic(DLRUtil.GetFieldPropertyBinder(fieldName), typeof(object), baseExpr); } else { throw new InvalidOperationException("Invalid children, expect either Property or Method call at this point"); } } else if (@operator.Type == TokenType.LBRACKET) { var indexExpr = nodes[start].GetAST(context); result = Expression.Dynamic(DLRUtil.GetIndexBinder(), typeof(object), baseExpr, indexExpr); } else { throw new InvalidOperationException(); } } return(result); }
private static Expression GetBinaryAST(IList <ParseNode> nodes, int start, Expression context) { //chain from left to right //2 + 3 + 4 is calculated as (2+3)+4, 15%12%5 as (15%12)%5 Debug.Assert(nodes.Count >= 3 && nodes.Count % 2 == 1); Expression result; if (start == 0) { result = nodes[start].GetAST(context); } else { var tokenType = nodes[start - 1].Token.Type; var left = GetBinaryAST(nodes, start - 2, context); var right = nodes[start].GetAST(context); if (tokenType == TokenType.AND) { result = Expression.AndAlso( Expression.Convert(left, typeof(bool)), Expression.Convert(right, typeof(bool))); } else if (tokenType == TokenType.OR) { result = Expression.OrElse( Expression.Convert(left, typeof(bool)), Expression.Convert(right, typeof(bool))); } else { result = Expression.Dynamic( DLRUtil.GetBinaryBinder(tokenType), typeof(object), left, right); } } return(result); }