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 = (NovaScope)rawScope; var defineScope = _inClassDefine ? scope : scope.GlobalScope; _inClassDefine = true; NovaClass parent; if (rawParent == null) { if (scope.GlobalScope["Object"] == null) { scope.GlobalScope["Object"] = Nova.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 = Nova.Box(dParent); } else { parent = dParent as NovaClass; } if (parent == null) { _inClassDefine = false; return(null); } } var name = (string)rawName; _className = name; var @class = new NovaClass { Name = _className, Parent = parent }; var xScope = new NovaScope(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 NovaModule)) { module = module.Context[mname]; } else if (index == 0) { module = scope[mname]; } index = index + 1; }); if (module != null) { if (module is NovaModule) { ((NovaModule)module).Contents.ForEach(mcon => { if (mcon is NovaFunction) { if ((mcon as NovaFunction).IsSingleton || (mcon as NovaFunction).Name == "new") { NovaClass.AddMethod(@class.ClassMethods, mcon as NovaFunction); } else { NovaClass.AddMethod(@class.InstanceMethods, mcon as NovaFunction); } if (@class.RemovedMethods.Contains((mcon as NovaFunction).Name)) { @class.RemovedMethods.Remove((mcon as NovaFunction).Name); } if (@class.UndefinedMethods.Contains((mcon as NovaFunction).Name)) { @class.UndefinedMethods.Remove((mcon as NovaFunction).Name); } } }); xScope.MergeWithScope(module.Context); } else if (module is NovaClass) { xScope[((NovaClass)module).Name] = module; } } } }); contents.ForEach(content => { if (!(content is IncludeExpression)) { var result = CompilerServices.CompileExpression(content, xScope); if (result is NovaFunction) { if ((result as NovaFunction).IsSingleton || (result as NovaFunction).Name == "new") { NovaClass.AddMethod(@class.ClassMethods, result as NovaFunction); } else { NovaClass.AddMethod(@class.InstanceMethods, result as NovaFunction); } if (@class.RemovedMethods.Contains((result as NovaFunction).Name)) { @class.RemovedMethods.Remove((result as NovaFunction).Name); } if (@class.UndefinedMethods.Contains((result as NovaFunction).Name)) { @class.UndefinedMethods.Remove((result as NovaFunction).Name); } } } }); if ([email protected]("new")) { NovaClass.AddMethod(@class.ClassMethods, new NovaFunction("new", new List <FunctionArgument>(), NovaExpression.NovaBlock( NovaExpression.Return(new List <FunctionArgument> { new FunctionArgument(null, NovaExpression.Variable(Expression.Constant("self"))) }), Expression.Label(NovaParser.ReturnTarget, Expression.Constant(null, typeof(object)))), new NovaScope())); } @class.Context = xScope; defineScope[@class.Name] = @class; _inClassDefine = false; return(@class); } }
internal static dynamic SingletonDefine(Expression rawSingleton, object rawName, object rawArguments, object rawBody, object rawScope) { var scope = (NovaScope)rawScope; var name = (string)rawName; var args = (List <FunctionArgument>)rawArguments; var body = (BlockExpression)rawBody; var function = new NovaFunction(name, args, body, scope); object singleton = CompilerServices.CompileExpression(rawSingleton, scope); if ((singleton is NovaClass)) { var @class = (NovaClass)singleton; if (_inClassDefine) { if (@class.Name == _className) { function.IsSingleton = true; return(function); } NovaClass.AddMethod(@class.InstanceMethods, function); if (@class.RemovedMethods.Contains(name)) { @class.RemovedMethods.Remove(name); } if (@class.UndefinedMethods.Contains(name)) { @class.UndefinedMethods.Remove(name); } } else { NovaClass.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 NovaInstance) { var @object = (NovaInstance)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(NovaClass @class, List <Expression> contents, object rawScope) { lock (_classDefineLock) { var scope = (NovaScope)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 NovaModule)) { module = module.Context[mname]; } else if (index == 0) { module = scope[mname]; } index = index + 1; }); if (module != null) { if (module is NovaModule) { ((NovaModule)module).Contents.ForEach(mcon => { if (mcon is NovaFunction) { if ((mcon as NovaFunction).IsSingleton || (mcon as NovaFunction).Name == "new") { NovaClass.AddMethod(@class.ClassMethods, mcon as NovaFunction); } else { NovaClass.AddMethod(@class.InstanceMethods, mcon as NovaFunction); } if (@class.RemovedMethods.Contains((mcon as NovaFunction).Name)) { @class.RemovedMethods.Remove((mcon as NovaFunction).Name); } if (@class.UndefinedMethods.Contains((mcon as NovaFunction).Name)) { @class.UndefinedMethods.Remove((mcon as NovaFunction).Name); } } }); scope.MergeWithScope(module.Context); } else if (module is NovaClass) { scope[((NovaClass)module).Name] = module; } } } }); contents.ForEach(content => { if (!(content is IncludeExpression)) { var result = CompilerServices.CompileExpression(content, scope); if (result is NovaFunction) { if ((result as NovaFunction).IsSingleton) { NovaClass.AddMethod(@class.ClassMethods, result as NovaFunction); } else { NovaClass.AddMethod(@class.InstanceMethods, result as NovaFunction); } if (@class.RemovedMethods.Contains((result as NovaFunction).Name)) { @class.RemovedMethods.Remove((result as NovaFunction).Name); } if (@class.UndefinedMethods.Contains((result as NovaFunction).Name)) { @class.UndefinedMethods.Remove((result as NovaFunction).Name); } } } }); @class.Context.MergeWithScope(scope); return(@class); } }