internal static dynamic CreateArray(List <Expression> values)
        {
            var list = new List <object>();

            values.ForEach(value => list.Add(CompilerServices.CreateLambdaForExpression(value)()));
            return(new NovaArray(list));
        }
예제 #2
0
        protected override Expression VisitVariable(VariableExpression node)
        {
            var name = CompilerServices.CreateLambdaForExpression(node.Name)();

            if (name is string)
            {
                _variableNames.Add(name);
            }
            return(node);
        }
        internal static dynamic CreateDictionary(IEnumerable <Expression> values)
        {
            var dict = new Dictionary <object, object>();

            foreach (var val in values.Select(_val => CompilerServices.CreateLambdaForExpression(_val)()))
            {
                dict[((KeyValuePair <object, object>)val).Key] = ((KeyValuePair <object, object>)val).Value;
            }
            return(new NovaDictionary(dict));
        }
예제 #4
0
        public override object Run(Scope scope)
        {
            var body = (Body as BlockExpression);

            body.Scope.MergeWithScope(Nova.Globals);
            body.Scope.MergeWithScope(scope);

            var visitor = new VariableNameVisitor();

            visitor.Visit(body);

            body.SetChildrenScopes(body.Scope);

            var block = CompilerServices.CreateLambdaForExpression(body);
            var res   = block();

            if (res is Symbol)
            {
                var symval = new BlockExpression(new List <Expression> {
                    new VariableExpression(res)
                }, body.Scope);
                res = CompilerServices.CreateLambdaForExpression(symval)();
            }
            else if (res is NovaInstance)
            {
                var so = (NovaInstance)res;
                if (so is NovaBoxedInstance)
                {
                    res = ((NovaBoxedInstance)so).BoxedObject;
                }
            }
            else if (res is NovaNumber)
            {
                res = NovaNumber.Convert(res);
            }
            else if (res is NovaString)
            {
                res = (string)res;
            }
            else if (res is NovaArray)
            {
                res = ConvertElements((NovaArray)res);
            }
            else if (res is NovaDictionary)
            {
                res = ConvertElements((NovaDictionary)res);
            }

            body.Scope.MergeIntoScope(scope);

            return(res);
        }
예제 #5
0
        internal object Run(NovaScope scope)
        {
            var body = (BlockExpression)Body;

            body.SetScope(scope);

            body.SetChildrenScopes(body.Scope);

            var block = CompilerServices.CreateLambdaForExpression(Expression.Block(body));

            var res = block();

            if (res is Symbol)
            {
                var symval = new BlockExpression(new List <Expression> {
                    new VariableExpression(res)
                }, body.Scope);
                res = CompilerServices.CreateLambdaForExpression(symval)();
            }

            return(res);
        }
예제 #6
0
 private static dynamic Dynamic(Type returnType, CallSiteBinder binder, IEnumerable <Expression> args)
 {
     return(CompilerServices.CreateLambdaForExpression(Expression.Dynamic(binder, returnType, args.ToArray()))());
 }
예제 #7
0
        private bool CheckForMatch(NovaNativeFunction function, List <FunctionArgument> args)
        {
            if (function.Arguments.Count == args.Count)
            {
                var _args = new List <object>();
                args.ForEach(arg => {
                    var val = CompilerServices.CreateLambdaForExpression(arg.Value)();
                    if (val is NovaString)
                    {
                        val = (string)val;
                    }
                    if (val is NovaNumber)
                    {
                        val = NovaNumber.Convert((NovaNumber)val);
                    }
                    _args.Add(val);
                });
                var match = true;
                var i     = 0;
                foreach (var param in function.Method.GetParameters())
                {
                    if (_args[i++].GetType() != param.ParameterType)
                    {
                        match = false;
                        break;
                    }
                }
                return(match);
            }
            if (args.Count > function.Arguments.Count)
            {
                if (function.Arguments.Any() && function.Arguments.Last().IsVarArg)
                {
                    return(true);
                }
                return(false);
            }
            var myCount    = args.Count;
            var theirCount = function.Arguments.Count;

            function.Arguments.ForEach(arg => {
                if (arg.HasDefault)
                {
                    theirCount--;
                }
            });
            var vo = 0;

            if (function.Arguments.Any() && function.Arguments.Last().IsVarArg)
            {
                vo = 1;
            }
            if (myCount == theirCount)
            {
                return(true);
            }
            if (myCount + vo == theirCount)
            {
                return(true);
            }
            return(false);
        }
        internal static dynamic Assign(VariableExpression @var, dynamic value, E type, bool isConst, object rawScope)
        {
            var scope = (NovaScope)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)
            {
                var iref = CompilerServices.CompileExpression(@var.Name as InstanceReferenceExpression, scope);
                var lval = CompilerServices.CompileExpression(iref.LValue, scope);
                if (map.ContainsKey(type))
                {
                    value =
                        CompilerServices.CreateLambdaForExpression(
                            NovaExpression.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)
                    {
                        var 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)
            {
                var sym = @var.Sym;

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

                if (map.ContainsKey(type))
                {
                    var nvalue =
                        CompilerServices.CreateLambdaForExpression(
                            NovaExpression.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)
                    {
                        var 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);
            }
            var found = false;

            if (name.StartsWith("@"))
            {
                if (scope["<nova_context_invokemember>"] != null)
                {
                    var ivar =
                        NovaExpression.Variable(
                            NovaExpression.InstanceRef(NovaExpression.Variable(Expression.Constant("self")),
                                                       Expression.Constant(name.Substring(1))));
                    if (map.ContainsKey(type))
                    {
                        value =
                            CompilerServices.CreateLambdaForExpression(
                                NovaExpression.Binary(ivar, Expression.Constant(value), map[type]))();
                    }
                    var assn = NovaExpression.Assign(NovaExpression.LeftHandValue(ivar), Expression.Constant(value));
                    return(CompilerServices.CompileExpression(assn, scope));
                }
                found = true;
                name  = name.Substring(1);
            }
            if (name == "self")
            {
                if (scope["<nova_context_selfname>"] != null &&
                    scope["<nova_context_selfscope>"] != null &&
                    scope["<nova_context_invokemember>"] != null)
                {
                    name  = scope["<nova_context_selfname>"];
                    scope = scope["<nova_context_selfscope>"];
                    found = true;
                }
            }
            while (scope.ParentScope != null && !found)
            {
                scope = scope.ParentScope;
                if (scope[name] != null)
                {
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                scope = (NovaScope)rawScope;
            }

            if (map.ContainsKey(type))
            {
                var nvalue =
                    CompilerServices.CreateLambdaForExpression(
                        NovaExpression.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)
                {
                    var 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);
        }
        internal static dynamic AccessSet(object container, List <FunctionArgument> args, object value, E type,
                                          object 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
            };

            var names = new List <string>();

            for (var i = 0; i < args.Count; i++)
            {
                names.Add(string.Format("index{0}", i));
            }

            var scope    = rawScope as NovaScope;
            var realArgs = new List <object>();

            args.ForEach(arg => realArgs.Add(CompilerServices.CompileExpression(arg.Value, scope)));


            if (map.ContainsKey(type))
            {
                var nvalue =
                    CompilerServices.CreateLambdaForExpression(
                        NovaExpression.Binary(Expression.Constant(Access(container, args, scope)),
                                              Expression.Constant(value),
                                              map[type]))();
                value = nvalue;
            }

            if (incDecMap.Contains(type))
            {
                if (type == E.PostIncrementAssign || type == E.PostDecrementAssign)
                {
                    var val = Access(container, args, scope);
                    AccessSet(container, args, 1, type == E.PostIncrementAssign ? E.AddAssign : E.SubtractAssign,
                              rawScope);
                    return(val);
                }
                AccessSet(container, args, 1, type == E.PreIncrementAssign ? E.AddAssign : E.SubtractAssign, rawScope);
                return(Access(container, args, scope));
            }

            var eArgs = new List <Expression>();

            eArgs.Add(Expression.Constant(container, typeof(object)));
            realArgs.ForEach(arg => eArgs.Add(Expression.Constant(arg)));
            eArgs.Add(Expression.Constant(value, typeof(object)));
            return(Dynamic(typeof(object),
                           new InteropBinder.SetIndex(scope, new CallInfo(args.Count, names)), eArgs));
        }