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);
            }
        }
Beispiel #2
0
        internal static dynamic SingletonDefine(Expression rawSingleton, object rawName, object rawArguments,
                                                object rawBody, object rawScope)
        {
            var scope = (KumaScope)rawScope;

            var name = (string)rawName;

            var args = (List <FunctionArgument>)rawArguments;

            var body     = (BlockExpression)rawBody;
            var function = new KumaFunction(name, args, body, scope);

            object singleton = CompilerServices.CompileExpression(rawSingleton, scope);

            if ((singleton is KumaClass))
            {
                var @class = (KumaClass)singleton;
                if (_inClassDefine)
                {
                    if (@class.Name == _className)
                    {
                        function.IsSingleton = true;
                        return(function);
                    }
                    KumaClass.AddMethod(@class.InstanceMethods, function);
                    if (@class.RemovedMethods.Contains(name))
                    {
                        @class.RemovedMethods.Remove(name);
                    }
                    if (@class.UndefinedMethods.Contains(name))
                    {
                        @class.UndefinedMethods.Remove(name);
                    }
                }
                else
                {
                    KumaClass.AddMethod(@class.InstanceMethods, function);
                    if (@class.RemovedMethods.Contains(name))
                    {
                        @class.RemovedMethods.Remove(name);
                    }
                    if (@class.UndefinedMethods.Contains(name))
                    {
                        @class.UndefinedMethods.Remove(name);
                    }
                }
            }
            else if (singleton is KumaInstance)
            {
                var @object = (KumaInstance)singleton;
                @object.SingletonMethods[name] = function;
                if (@object.RemovedMethods.Contains(name))
                {
                    @object.RemovedMethods.Remove(name);
                }
                if (@object.UndefinedMethods.Contains(name))
                {
                    @object.UndefinedMethods.Remove(name);
                }
            }

            return(function);
        }
        internal static dynamic DefineCategory(KumaClass @class, List <Expression> contents, object rawScope)
        {
            lock (_classDefineLock) {
                var scope = (KumaScope)rawScope;
                _inClassDefine = true;
                _className     = @class.Name;

                scope["self"]      = @class;
                scope[_className]  = @class;
                _currentClassScope = scope;

                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 != null && (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);
                                        }
                                    }
                                });

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

                contents.ForEach(content => {
                    if (!(content is IncludeExpression))
                    {
                        var result = CompilerServices.CompileExpression(content, scope);
                        if (result is KumaFunction)
                        {
                            if ((result as KumaFunction).IsSingleton)
                            {
                                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);
                            }
                        }
                    }
                });

                @class.Context.MergeWithScope(scope);
                return(@class);
            }
        }