protected override Expression VisitVariable(VariableExpression node)
 {
     dynamic name = CompilerServices.CreateLambdaForExpression(node.Name)();
     if (name is string) {
         _variableNames.Add(name);
     }
     return node;
 }
 internal static dynamic ConditionalAssign(VariableExpression @var, dynamic value, bool isOrAssign, bool isConst,
     object rawScope)
 {
     var scope = rawScope as SilverScope;
     dynamic v = Resolve(CompilerServices.CompileExpression(@var.Name, scope), scope);
     if (Boolean(v)) {
         if (!isOrAssign) {
             return Assign(@var, value, E.Assign, isConst, scope);
         }
     }
     else {
         if (isOrAssign) {
             return Assign(@var, value, E.Assign, isConst, scope);
         }
     }
     return v;
 }
        internal static dynamic Assign(VariableExpression @var, dynamic value, E type, bool isConst, object rawScope)
        {
            var scope = (SilverScope) rawScope;
            var map = new Dictionary<ExpressionType, ExpressionType>();
            map[E.AddAssign] = E.Add;
            map[E.AndAssign] = E.And;
            map[E.DivideAssign] = E.Divide;
            map[E.ExclusiveOrAssign] = E.ExclusiveOr;
            map[E.LeftShiftAssign] = E.LeftShift;
            map[E.ModuloAssign] = E.Modulo;
            map[E.MultiplyAssign] = E.Multiply;
            map[E.OrAssign] = E.Or;
            map[E.PowerAssign] = E.Power;
            map[E.RightShiftAssign] = E.RightShift;
            map[E.SubtractAssign] = E.Subtract;

            var incDecMap = new List<ExpressionType> {
                E.PreIncrementAssign,
                E.PreDecrementAssign,
                E.PostIncrementAssign,
                E.PostDecrementAssign
            };

            if (@var.Name is InstanceReferenceExpression) {
                dynamic iref = CompilerServices.CompileExpression(@var.Name as InstanceReferenceExpression, scope);
                dynamic lval = CompilerServices.CompileExpression(iref.LValue, scope);
                if (map.ContainsKey(type)) {
                    value =
                        CompilerServices.CreateLambdaForExpression(
                            AstExpression.Binary(
                                Expression.Constant(Resolve(CompilerServices.CompileExpression(iref, scope), scope)),
                                Expression.Constant(value), map[type]))();
                }
                if (incDecMap.Contains(type)) {
                    var gmArgs = new List<Expression>();
                    gmArgs.Add(Expression.Constant(lval, typeof (object)));
                    if (type == E.PreIncrementAssign || type == E.PreDecrementAssign) {
                        dynamic val = Resolve(CompilerServices.CompileExpression(iref, scope), scope);
                        Assign(@var, 1, type == E.PreIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope);
                        return val;
                    }
                    Assign(@var, 1, type == E.PostIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope);
                    return Resolve(CompilerServices.CompileExpression(iref, scope), scope);
                }

                var smArgs = new List<Expression>();
                smArgs.Add(Expression.Constant(lval, typeof (object)));
                smArgs.Add(Expression.Constant(value, typeof (object)));
                return Dynamic(typeof (object), new InteropBinder.SetMember(iref.Key, scope), smArgs);
            }
            if (@var.HasSym) {
                Symbol sym = @var.Sym;

                bool symFound = false;
                while (scope.ParentScope != null) {
                    scope = scope.ParentScope;
                    if (scope[sym] != null) {
                        symFound = true;
                        break;
                    }
                }
                if (!symFound) {
                    scope = (SilverScope) rawScope;
                }

                if (map.ContainsKey(type)) {
                    dynamic nvalue =
                        CompilerServices.CreateLambdaForExpression(
                            AstExpression.Binary(Expression.Constant(ResolveSymbol(sym, scope)),
                                Expression.Constant(value), map[type]))();
                    scope[sym] = nvalue;
                    return nvalue;
                }

                if (incDecMap.Contains(type)) {
                    if (type == E.PreIncrementAssign || type == E.PreDecrementAssign) {
                        dynamic val = ResolveSymbol(sym, scope);
                        Assign(@var, 1, type == E.PreIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope);
                        return val;
                    }
                    Assign(@var, 1, type == E.PostIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope);
                    return ResolveSymbol(sym, scope);
                }

                scope[sym] = value;
                if (isConst) {
                    scope.Constants.Add(sym.Name);
                }
                return value;
            }
            string name = CompilerServices.CompileExpression(@var.Name, scope);
            if (name.StartsWith("$") && name != "$:") {
                scope = scope.GlobalScope;
                name = name.Substring(1);
            }
            bool found = false;
            if (name.StartsWith("@")) {
                if (scope["<ironsilver_context_invokemember>"] != null) {
                    VariableExpression ivar =
                        AstExpression.Variable(
                            AstExpression.InstanceRef(AstExpression.Variable(Expression.Constant("self")),
                                Expression.Constant(name.Substring(1))));
                    if (map.ContainsKey(type)) {
                        value =
                            CompilerServices.CreateLambdaForExpression(
                                AstExpression.Binary(ivar, Expression.Constant(value), map[type]))();
                    }
                    dynamic assn = AstExpression.Assign(AstExpression.LeftHandValue(ivar), Expression.Constant(value));
                    return CompilerServices.CompileExpression(assn, scope);
                }
                found = true;
                name = name.Substring(1);
            }
            if (name == "self")
            {
                if (scope["<ironsilver_context_selfname>"] != null &&
                    scope["<ironsilver_context_selfscope>"] != null &&
                    scope["<ironsilver_context_invokemember>"] != null)
                {
                    name = scope["<ironsilver_context_selfname>"];
                    scope = scope["<ironsilver_context_selfscope>"];
                    found = true;
                }
            }
            while (scope.ParentScope != null && !found) {
                scope = scope.ParentScope;
                if (scope[name] != null) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                scope = (SilverScope) rawScope;
            }

            if (map.ContainsKey(type)) {
                dynamic nvalue =
                    CompilerServices.CreateLambdaForExpression(
                        AstExpression.Binary(Expression.Constant(Resolve(name, scope)), Expression.Constant(value),
                            map[type]))();
                scope[name] = nvalue;
                return nvalue;
            }

            if (incDecMap.Contains(type)) {
                if (type == E.PostIncrementAssign || type == E.PostDecrementAssign) {
                    dynamic val = Resolve(name, scope);
                    Assign(@var, 1, type == E.PostIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope);
                    return val;
                }
                Assign(@var, 1, type == E.PreIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope);
                return Resolve(name, scope);
            }

            scope[name] = value;
            if (isConst) {
                scope.Constants.Add(name);
            }
            return value;
        }
 protected virtual Expression VisitVariable(VariableExpression node)
 {
     return node;
 }