internal static dynamic Switch(object rawTest, List <SwitchCase> cases, object rawDefaultBlock, object rawScope)
        {
            var test         = (Expression)rawTest;
            var defaultBlock = rawDefaultBlock != null
                ? (Expression)rawDefaultBlock
                : KumaExpression.KumaBlock(KumaExpression.Default(cases.First().Body.Type));
            var scope = (KumaScope)rawScope;

            dynamic retVal = null;

            var found = false;
            var tval  = CompilerServices.CompileExpression(test, scope);

            foreach (var @case in cases.Where(@case => @case.TestValues.Select(testValue => CompilerServices.CompileExpression(testValue, scope))
                                              .Any(xval => Binary(tval, xval, E.Equal, scope))))
            {
                found  = true;
                retVal = CompilerServices.CompileExpression(@case.Body, scope);
            }

            if (!found)
            {
                retVal = CompilerServices.CompileExpression(defaultBlock, scope);
            }

            return(retVal);
        }
Пример #2
0
        private static dynamic InstanceEval(object self, string eval, KumaScope scope)
        {
            if (!(self is KumaInstance instance))
            {
                return(null);
            }

            var        xexpression = string.Format("{0};", eval);
            var        res         = KumaParser.Parse(xexpression);
            Expression block;

            if (res != null)
            {
                scope["self"] = scope["super"] = instance;
                scope["<kuma_context_invokemember>"] = true;
                string selfName;
                var    selfScope = scope.SearchForObject(instance, out selfName);
                if (selfScope != null && selfName != null)
                {
                    scope["<kuma_context_selfscope>"] = selfScope;
                    scope["<kuma_context_selfname>"]  = selfName;
                }
                block = KumaExpression.KumaBlock(res);
                // We want eval'd expressions to execute in the current scope, not its own child scopes.  This ensures assignment evals work properly.
                ((BlockExpression)block).Scope = scope;
                ((BlockExpression)block).SetChildrenScopes(scope);
            }
            else
            {
                return(null);
            }
            var val = CompilerServices.CreateLambdaForExpression(block)();

            return(val);
        }
Пример #3
0
 internal static Expression Op(string op, Type expectedType, params Expression[] args)
 {
     if (op == "Convert")
     {
         return(Expression.Convert(Expression.Call(null, OpToMethod(op), args), expectedType));
     }
     return(KumaExpression.Convert(Expression.Call(null, OpToMethod(op), args), expectedType));
 }
        internal static dynamic CompileExpression(Expression e, KumaScope scope)
        {
            Expression newExpression = KumaExpression.Convert(e, typeof(object));

            newExpression.SetScope(scope);
            var l = CreateLambdaForExpression(newExpression);

            return(l());
        }
Пример #5
0
        internal static dynamic Resolve(object rawName, object rawScope)
        {
            if (rawName.GetType() == typeof(InstanceReference))
            {
                var iref   = (InstanceReference)rawName;
                var lval   = CompilerServices.CompileExpression(iref.LValue, (KumaScope)rawScope);
                var gmArgs = new List <Expression> ();
                gmArgs.Add(Expression.Constant(lval, typeof(object)));
                return(Dynamic(typeof(object), new InteropBinder.GetMember(iref.Key, (KumaScope)rawScope), gmArgs));
            }
            var name  = (string)rawName;
            var scope = (KumaScope)rawScope;

            if (name.StartsWith("$") && name != "$:")
            {
                scope = scope.GlobalScope;
                name  = name.Substring(1);
            }
            if (name.StartsWith("@") && scope["<kuma_context_invokemember>"] != null)
            {
                if (name.StartsWith("@@"))
                {
                    var _val = Resolve("self", scope);
                    if (!(_val is KumaInstance))
                    {
                        // native object?
                        _val = Kuma.Box((object)_val, scope);
                    }
                    var @class = ((KumaInstance)_val).Class;
                    return
                        (CompilerServices.CompileExpression(
                             KumaExpression.Variable(KumaExpression.InstanceRef(Expression.Constant(@class),
                                                                                Expression.Constant(name.Substring(2)))), scope));
                }
                return
                    (CompilerServices.CompileExpression(
                         KumaExpression.Variable(
                             KumaExpression.InstanceRef(KumaExpression.Variable(Expression.Constant("self")),
                                                        Expression.Constant(name.Substring(1)))), scope));
            }

            var val = scope[name];

            // The cast is needed here because if we get a non-nullable type (such as System.Int32) the check here will throw an exception.
            // By casting to System.Object we can avoid the exception since it is a boxed value that can be null.
            if ((object)val == null)
            {
                Type type;
                if ((type = KumaTypeResolver.Resolve(name)) != null)
                {
                    var @class = KumaClass.BoxClass(type);
                    scope.GlobalScope[@class.Name] = @class;
                    val = @class;
                }
            }
            return(val);
        }
        public static BlockExpression GenerateBody(Type type, MethodBase method)
        {
            var body = new List <Expression>();

            body.Add(
                KumaExpression.Invoke(
                    Expression.Constant(method.IsConstructor ? typeof(KumaInstance) : type, typeof(Type)),
                    Expression.Constant(method, typeof(MethodBase)), ArgumentCache[method]));
            body.Add(Expression.Label(KumaParser.ReturnTarget, Expression.Constant(null, typeof(object))));
            return(KumaExpression.KumaBlock(body.ToArray()));
        }
Пример #7
0
        public override ScriptCode CompileSourceCode(SourceUnit sourceUnit, CompilerOptions options, ErrorSink errorSink)
        {
            var res = KumaParser.Parse(sourceUnit.GetCode(), sourceUnit);

            if (res != null)
            {
                Expression mainBlock = KumaExpression.KumaBlock(res);
                return(new KumaScriptCode(mainBlock, sourceUnit));
            }
            else
            {
                throw new SyntaxErrorException("Syntax error", sourceUnit, SourceSpan.None, 0, Severity.Error);
            }
        }
Пример #8
0
 protected void AddRestrictions(DynamicMetaObject[] args)
 {
     foreach (var arg in args)
     {
         if (arg.Restrictions != BindingRestrictions.Empty)
         {
             AddRestriction(arg.Restrictions);
         }
         else
         {
             // Runtime check!
             AddRestriction(
                 BindingRestrictions.GetExpressionRestriction(KumaExpression.Binary(arg.Expression,
                                                                                    Expression.Constant(arg.Value), ExpressionType.Equal)));
         }
     }
 }
Пример #9
0
        private static dynamic Eval(string eval, KumaScope scope)
        {
            var xexpression = string.Format("{0};", eval);

            var        res = KumaParser.Parse(xexpression);
            Expression block;

            if (res != null)
            {
                block = KumaExpression.KumaBlock(res);
                // We want eval'd expressions to execute in the current scope, not its own child scopes.  This ensures assignment evals work properly.
                ((BlockExpression)block).Scope = scope;
                ((BlockExpression)block).SetChildrenScopes(scope);
            }
            else
            {
                return(null);
            }
            var val = CompilerServices.CreateLambdaForExpression(block)();

            return(val);
        }
Пример #10
0
 public KumaClass(string name, KumaClass parent, List <KumaFunction> classMethods,
                  List <KumaFunction> instanceMethods)
 {
     Name         = name;
     ClassMethods = new Dictionary <string, KumaMethodTable>();
     classMethods.ForEach(func => AddMethod(ClassMethods, func));
     if (!ClassMethods.ContainsKey("new"))
     {
         AddMethod(ClassMethods, new KumaFunction("new", new List <FunctionArgument>(),
                                                  KumaExpression.KumaBlock(
                                                      KumaExpression.Return(new List <FunctionArgument> {
             new FunctionArgument(null, KumaExpression.Variable(Expression.Constant("self")))
         }),
                                                      Expression.Label(KumaParser.ReturnTarget, Expression.Constant(null, typeof(object)))),
                                                  new KumaScope()));
     }
     InstanceMethods = new Dictionary <string, KumaMethodTable>();
     instanceMethods.ForEach(func => AddMethod(InstanceMethods, func));
     UndefinedMethods = new List <string>();
     RemovedMethods   = new List <string>();
     Context          = new KumaScope();
     Parent           = parent;
 }
Пример #11
0
        internal static dynamic String(object rawEval, object rawScope)
        {
            StringBuilder @new;
            var           eval = rawEval as String;

            var components = eval.Split(new[] { "#{" }, StringSplitOptions.None);

            if (components.Count() == 1)
            {
                return(new KumaString(eval));
            }
            @new = new StringBuilder(components[0]);
            for (var i = 1; i < components.Count(); i++)
            {
                var parts        = components[i].Split(new[] { "}" }, StringSplitOptions.None);
                var expression   = parts[0];
                var escapeString = false;
                if (expression != null && expression[0] == ':')
                {
                    escapeString = true;
                    expression   = expression.Substring(1);
                }
                if (expression != null)
                {
                    var scope       = (KumaScope)rawScope;
                    var xexpression = string.Format("{0};", expression);

                    var        res = KumaParser.Parse(xexpression);
                    Expression block;
                    if (res != null)
                    {
                        block = KumaExpression.KumaBlock(res);
                    }
                    else
                    {
                        return(null);
                    }
                    var myScope = new KumaScope();
                    var visitor = new VariableNameVisitor();
                    visitor.Visit(block);
                    visitor.VariableNames.ForEach(name => myScope[name] = scope[name]);
                    var val = CompilerServices.CompileExpression(block, myScope);
                    if (val != null)
                    {
                        string stringVal = val.ToString();
                        if (escapeString && val is string)
                        {
                            stringVal = string.Format("\"{0}\"", stringVal);
                        }
                        @new.Append(stringVal ?? "");
                    }
                    else
                    {
                        @new.Append(expression);
                    }
                }
                if (parts.Count() > 1)
                {
                    @new.Append(parts[1]);
                    var j = 2;
                    while (j < parts.Count())
                    {
                        @new.Append("}");
                        @new.Append(parts[j++]);
                    }
                }
            }

            return(new KumaString(@new.ToString()));
        }
Пример #12
0
        internal static dynamic Assign(VariableExpression @var, dynamic value, E type, bool isConst, object rawScope)
        {
            var scope = (KumaScope)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(
                            KumaExpression.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 = (KumaScope)rawScope;
                }

                if (map.ContainsKey(type))
                {
                    var nvalue =
                        CompilerServices.CreateLambdaForExpression(
                            KumaExpression.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["<kuma_context_invokemember>"] != null)
                {
                    var ivar =
                        KumaExpression.Variable(
                            KumaExpression.InstanceRef(KumaExpression.Variable(Expression.Constant("self")),
                                                       Expression.Constant(name.Substring(1))));
                    if (map.ContainsKey(type))
                    {
                        value =
                            CompilerServices.CreateLambdaForExpression(
                                KumaExpression.Binary(ivar, Expression.Constant(value), map[type])) ();
                    }
                    var assn = KumaExpression.Assign(KumaExpression.LeftHandValue(ivar), Expression.Constant(value));
                    return(CompilerServices.CompileExpression(assn, scope));
                }
                found = true;
                name  = name.Substring(1);
            }
            if (name == "self")
            {
                if (scope["<kuma_context_selfname>"] != null &&
                    scope["<kuma_context_selfscope>"] != null &&
                    scope["<kuma_context_invokemember>"] != null)
                {
                    name  = scope["<kuma_context_selfname>"];
                    scope = scope["<kuma_context_selfscope>"];
                    found = true;
                }
            }
            while (scope.ParentScope != null && !found)
            {
                scope = scope.ParentScope;
                if (scope[name] != null)
                {
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                scope = (KumaScope)rawScope;
            }

            if (map.ContainsKey(type))
            {
                var nvalue =
                    CompilerServices.CreateLambdaForExpression(
                        KumaExpression.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 DefineClass(object rawName, object rawParent, List <Expression> contents, object rawScope)
        {
            lock (_classDefineLock) {
                if (Resolve(rawName, rawScope) != null)
                {
                    return(DefineCategory(Resolve(rawName, rawScope), contents, rawScope));
                }
                var scope       = (KumaScope)rawScope;
                var defineScope = _inClassDefine ? scope : scope.GlobalScope;
                _inClassDefine = true;
                KumaClass parent;
                if (rawParent == null)
                {
                    if (scope.GlobalScope["Object"] == null)
                    {
                        scope.GlobalScope["Object"] = Kuma.Box(typeof(object));
                    }
                    parent = scope.GlobalScope["Object"];
                }
                else
                {
                    var dParent = Resolve(rawParent as string, scope);
                    if (dParent == null)
                    {
                        _inClassDefine = false;
                        return(null);
                    }
                    if (dParent is Type)
                    {
                        parent = Kuma.Box(dParent);
                    }
                    else
                    {
                        parent = dParent as KumaClass;
                    }
                    if (parent == null)
                    {
                        _inClassDefine = false;
                        return(null);
                    }
                }

                var name = (string)rawName;
                _className = name;

                var @class = new KumaClass {
                    Name = _className, Parent = parent
                };
                var xScope = new KumaScope(scope);
                xScope["self"]     = @class;
                xScope[_className] = @class;
                _currentClassScope = xScope;

                contents.ForEach(content => {
                    if (content is IncludeExpression)
                    {
                        // We only include modules here so make sure this include references a module
                        var names = ((IncludeExpression)content).Names;

                        dynamic module = null;

                        var index = 0;
                        names.ForEach(mname => {
                            if ((module is KumaModule))
                            {
                                module = module.Context[mname];
                            }
                            else if (index == 0)
                            {
                                module = scope[mname];
                            }
                            index = index + 1;
                        });

                        if (module != null)
                        {
                            if (module is KumaModule)
                            {
                                ((KumaModule)module).Contents.ForEach(mcon => {
                                    if (mcon is KumaFunction)
                                    {
                                        if ((mcon as KumaFunction).IsSingleton ||
                                            (mcon as KumaFunction).Name == "new")
                                        {
                                            KumaClass.AddMethod(@class.ClassMethods, mcon as KumaFunction);
                                        }
                                        else
                                        {
                                            KumaClass.AddMethod(@class.InstanceMethods, mcon as KumaFunction);
                                        }
                                        if (@class.RemovedMethods.Contains((mcon as KumaFunction).Name))
                                        {
                                            @class.RemovedMethods.Remove((mcon as KumaFunction).Name);
                                        }
                                        if (@class.UndefinedMethods.Contains((mcon as KumaFunction).Name))
                                        {
                                            @class.UndefinedMethods.Remove((mcon as KumaFunction).Name);
                                        }
                                    }
                                });

                                xScope.MergeWithScope(module.Context);
                            }
                            else if (module is KumaClass)
                            {
                                xScope[((KumaClass)module).Name] = module;
                            }
                        }
                    }
                });

                contents.ForEach(content => {
                    if (!(content is IncludeExpression))
                    {
                        var result = CompilerServices.CompileExpression(content, xScope);
                        if (result is KumaFunction)
                        {
                            if ((result as KumaFunction).IsSingleton || (result as KumaFunction).Name == "new")
                            {
                                KumaClass.AddMethod(@class.ClassMethods, result as KumaFunction);
                            }
                            else
                            {
                                KumaClass.AddMethod(@class.InstanceMethods, result as KumaFunction);
                            }
                            if (@class.RemovedMethods.Contains((result as KumaFunction).Name))
                            {
                                @class.RemovedMethods.Remove((result as KumaFunction).Name);
                            }
                            if (@class.UndefinedMethods.Contains((result as KumaFunction).Name))
                            {
                                @class.UndefinedMethods.Remove((result as KumaFunction).Name);
                            }
                        }
                    }
                });

                if ([email protected]("new"))
                {
                    KumaClass.AddMethod(@class.ClassMethods, new KumaFunction("new", new List <FunctionArgument>(),
                                                                              KumaExpression.KumaBlock(
                                                                                  KumaExpression.Return(new List <FunctionArgument> {
                        new FunctionArgument(null, KumaExpression.Variable(Expression.Constant("self")))
                    }),
                                                                                  Expression.Label(KumaParser.ReturnTarget, Expression.Constant(null, typeof(object)))),
                                                                              new KumaScope()));
                }
                @class.Context           = xScope;
                defineScope[@class.Name] = @class;
                _inClassDefine           = false;
                return(@class);
            }
        }
Пример #14
0
        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 KumaScope;
            var realArgs = new List <object>();

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


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