Пример #1
0
        // AnalyzeLetStar returns a Block with vars, each initialized in the order
        // they appear.  Each var's init expr can refer to vars initialized before it.
        // The Block's body is the Let*'s body.
        //
        public static Expression AnalyzeLetStarExpr(SymplLetStarExpr expr,
                                                    AnalysisScope scope)
        {
            var letscope = new AnalysisScope(scope, "let*");
            // Analyze bindings.
            List <Expression>          inits       = new List <Expression>();
            List <ParameterExpression> varsInOrder = new List <ParameterExpression>();

            foreach (var b in expr.Bindings)
            {
                // Need richer logic for mvbind
                var v = Expression.Parameter(typeof(object), b.Variable.Name);
                varsInOrder.Add(v);
                inits.Add(
                    Expression.Assign(
                        v,
                        Expression.Convert(AnalyzeExpr(b.Value, letscope), v.Type))
                    );
                // Add var to scope after analyzing init value so that init value
                // references to the same ID do not bind to his uninitialized var.
                letscope.Names[b.Variable.Name.ToLower()] = v;
            }
            List <Expression> body = new List <Expression>();

            foreach (var e in expr.Body)
            {
                body.Add(AnalyzeExpr(e, letscope));
            }
            // Order of vars to BlockExpr don't matter semantically, but may as well
            // keep them in the order the programmer specified in case they look at the
            // Expr Trees in the debugger or for meta-programming.
            inits.AddRange(body);
            return(Expression.Block(typeof(object), varsInOrder.ToArray(), inits));
        }
Пример #2
0
        public static Expression AnalyzeBinaryExpr(SymplBinaryExpr expr,
                                                   AnalysisScope scope)
        {
            // The language has the following special logic to handle And and Or
            // x And y == if x then y
            // x Or y == if x then x else (if y then y)
            if (expr.Operation == ExpressionType.And)
            {
                return(AnalyzeIfExpr(
                           new SymplIfExpr(
                               expr.Left, expr.Right, null),
                           scope));
            }
            else if (expr.Operation == ExpressionType.Or)
            {
                // Use (LetStar (tmp expr) (if tmp tmp)) to represent (if expr expr)
                // to remore duplicate evaluation.
                // So x Or y is translated into
                // (Let* (tmp1 x)
                //    (If tmp1 tmp1
                //       (Let* (tmp2 y) (If tmp2 tmp2))))
                //

                IdOrKeywordToken tmp2 = new IdOrKeywordToken(
                    // Real implementation needs to ensure unique ID in scope chain.
                    "__tmpLetVariable2");
                var tmpExpr2 = new SymplIdExpr(tmp2);
                var binding2 = new LetBinding(tmp2, expr.Right);;
                var ifExpr2  = new SymplIfExpr(
                    tmpExpr2, tmpExpr2, null);
                var letExpr2 = new SymplLetStarExpr(
                    new[] { binding2 },
                    new[] { ifExpr2 });

                IdOrKeywordToken tmp1 = new IdOrKeywordToken(
                    // Real implementation needs to ensure unique ID in scope chain.
                    "__tmpLetVariable1");
                var        tmpExpr1 = new SymplIdExpr(tmp1);
                LetBinding binding1 = new LetBinding(tmp1, expr.Left);;
                SymplExpr  ifExpr1  = new SymplIfExpr(
                    tmpExpr1, tmpExpr1, letExpr2);
                return(AnalyzeLetStarExpr(
                           new SymplLetStarExpr(
                               new[] { binding1 },
                               new[] { ifExpr1 }
                               ),
                           scope
                           ));
            }

            return(Expression.Dynamic(
                       scope.GetRuntime().GetBinaryOperationBinder(expr.Operation),
                       typeof(object),
                       AnalyzeExpr(expr.Left, scope),
                       AnalyzeExpr(expr.Right, scope)
                       ));
        }