Beispiel #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));
        }
Beispiel #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)
                       ));
        }
Beispiel #3
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)
            );
        }
Beispiel #4
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);
        }