PageRenderTime 56ms CodeModel.GetById 38ms app.highlight 13ms RepoModel.GetById 2ms app.codeStats 0ms

/IronPython_Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Extensions/TypeGroupOps.cs

#
C# | 195 lines | 144 code | 33 blank | 18 comment | 15 complexity | 2e1eeea60c4779924f5f00d1cbbfaa50 MD5 | raw file
  1/* ****************************************************************************
  2 *
  3 * Copyright (c) Microsoft Corporation. 
  4 *
  5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
  6 * copy of the license can be found in the License.html file at the root of this distribution. If 
  7 * you cannot locate the  Apache License, Version 2.0, please send an email to 
  8 * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
  9 * by the terms of the Apache License, Version 2.0.
 10 *
 11 * You must not remove this notice, or any other, from this software.
 12 *
 13 *
 14 * ***************************************************************************/
 15
 16#if !CLR2
 17using System.Linq.Expressions;
 18#else
 19using Microsoft.Scripting.Ast;
 20#endif
 21
 22using System;
 23using System.Dynamic;
 24using Microsoft.Scripting.Runtime;
 25using Microsoft.Scripting.Actions;
 26using IronRuby.Runtime;
 27using IronRuby.Runtime.Calls;
 28using IronRuby.Compiler.Generation;
 29using System.Runtime.CompilerServices;
 30using System.Collections.Generic;
 31using Microsoft.Scripting.Utils;
 32
 33namespace IronRuby.Builtins {
 34    using Ast = Expression;
 35    using AstUtils = Microsoft.Scripting.Ast.Utils;
 36
 37    [RubyClass(Extends = typeof(TypeGroup), Restrictions = ModuleRestrictions.None)]
 38    [Includes(typeof(Enumerable))]
 39    public static class TypeGroupOps {
 40        [RubyMethod("of")]
 41        [RubyMethod("[]")]
 42        public static RubyModule/*!*/ Of(RubyContext/*!*/ context, TypeGroup/*!*/ self, [NotNullItems]params object/*!*/[]/*!*/ typeArgs) {
 43            TypeTracker tracker = self.GetTypeForArity(typeArgs.Length);
 44
 45            if (tracker == null) {
 46                throw RubyExceptions.CreateArgumentError("Invalid number of type arguments for `{0}'", self.Name);
 47            }
 48
 49            Type concreteType;
 50            if (typeArgs.Length > 0) {
 51                concreteType = tracker.Type.MakeGenericType(Protocols.ToTypes(context, typeArgs));
 52            } else {
 53                concreteType = tracker.Type;
 54            }
 55
 56            return context.GetModule(concreteType);
 57        }
 58
 59        [RubyMethod("of")]
 60        [RubyMethod("[]")]
 61        public static RubyModule/*!*/ Of(RubyContext/*!*/ context, TypeGroup/*!*/ self, int genericArity) {
 62            TypeTracker tracker = self.GetTypeForArity(genericArity);
 63            if (tracker == null) {
 64                throw RubyExceptions.CreateArgumentError("Type group `{0}' does not contain a type of generic arity {1}", self.Name, genericArity);
 65            }
 66
 67            return context.GetModule(tracker.Type);
 68        }
 69
 70        [RubyMethod("each")]
 71        public static object EachType(RubyContext/*!*/ context, BlockParam/*!*/ block, TypeGroup/*!*/ self) {
 72            if (block == null) {
 73                throw RubyExceptions.NoBlockGiven();
 74            }
 75
 76            foreach (Type type in self.Types) {
 77                RubyModule module = context.GetModule(type);
 78                object result;
 79                if (block.Yield(module, out result)) {
 80                    return result;
 81                }
 82            }
 83
 84            return self;
 85        }
 86
 87        [RubyMethod("name")]
 88        [RubyMethod("to_s")]
 89        public static MutableString/*!*/ GetName(RubyContext/*!*/ context, TypeGroup/*!*/ self) {
 90            return MutableString.Create(self.Name, context.GetIdentifierEncoding());
 91        }
 92
 93        [RubyMethod("inspect")]
 94        public static MutableString/*!*/ Inspect(RubyContext/*!*/ context, TypeGroup/*!*/ self) {
 95            var result = MutableString.CreateMutable(context.GetIdentifierEncoding());
 96            result.Append("#<TypeGroup: ");
 97
 98            bool isFirst = true;
 99            foreach (var entry in self.TypesByArity.ToSortedList((x, y) => x.Key - y.Key)) {
100                Type type = entry.Value;
101
102                if (!isFirst) {
103                    result.Append(", ");
104                } else {
105                    isFirst = false;
106                }
107
108                result.Append(context.GetTypeName(type, true));
109            }
110            result.Append('>');
111
112            return result;
113        }
114
115        private static Type/*!*/ GetNonGenericType(TypeGroup/*!*/ self) {
116            TypeTracker type = self.GetTypeForArity(0);
117            if (type == null) {
118                throw RubyExceptions.CreateTypeError("type group doesn't include non-generic type");
119            }
120
121            return type.Type;
122        }
123
124        [Emitted]
125        public static RubyClass/*!*/ GetNonGenericClass(RubyContext/*!*/ context, TypeGroup/*!*/ typeGroup) {
126            Type type = GetNonGenericType(typeGroup);
127            if (type.IsInterface) {
128                throw RubyExceptions.CreateTypeError("cannot instantiate an interface");
129            }
130            return context.GetClass(type);
131        }
132
133        private static object New(string/*!*/ methodName, CallSiteStorage<Func<CallSite, object, object, object>>/*!*/ storage,
134            TypeGroup/*!*/ self, params object[]/*!*/ args) {
135
136            var cls = GetNonGenericClass(storage.Context, self);
137            var site = storage.GetCallSite(methodName,
138                new RubyCallSignature(1, RubyCallFlags.HasImplicitSelf | RubyCallFlags.HasSplattedArgument)
139            );
140
141            return site.Target(site, cls, RubyOps.MakeArrayN(args));
142        }
143
144        private static object New(string/*!*/ methodName, CallSiteStorage<Func<CallSite, object, object, object, object>>/*!*/ storage, BlockParam block, 
145            TypeGroup/*!*/ self, params object[]/*!*/ args) {
146
147            var cls = GetNonGenericClass(storage.Context, self);
148            var site = storage.GetCallSite(methodName,
149                new RubyCallSignature(1, RubyCallFlags.HasImplicitSelf | RubyCallFlags.HasSplattedArgument | RubyCallFlags.HasBlock)
150            );
151
152            return site.Target(site, cls, block != null ? block.Proc : null, RubyOps.MakeArrayN(args));
153        }
154
155        // ARGS: N
156        [RubyMethod("new")]
157        public static object/*!*/ New(CallSiteStorage<Func<CallSite, object, object, object>>/*!*/ storage, 
158            TypeGroup/*!*/ self, params object[]/*!*/ args) {
159            return New("new", storage, self, args);
160        }
161
162        // ARGS: N&
163        [RubyMethod("new")]
164        public static object New(CallSiteStorage<Func<CallSite, object, object, object, object>>/*!*/ storage, BlockParam block, 
165            TypeGroup/*!*/ self, params object[]/*!*/ args) {
166            return New("new", storage, block, self, args);
167        }
168
169        [RubyMethod("superclass")]
170        public static RubyClass GetSuperclass(RubyContext/*!*/ context, TypeGroup/*!*/ self) {
171            Type type = GetNonGenericType(self);
172            return type.IsInterface ? null : context.GetClass(type).SuperClass;
173        }
174
175        // ARGS: N
176        [RubyMethod("clr_new")]
177        public static object/*!*/ ClrNew(CallSiteStorage<Func<CallSite, object, object, object>>/*!*/ storage,
178            TypeGroup/*!*/ self, params object[]/*!*/ args) {
179            return New("clr_new", storage, self, args);
180        }
181
182        // ARGS: N&
183        [RubyMethod("clr_new")]
184        public static object ClrNew(CallSiteStorage<Func<CallSite, object, object, object, object>>/*!*/ storage, BlockParam block,
185            TypeGroup/*!*/ self, params object[]/*!*/ args) {
186            return New("clr_new", storage, block, self, args);
187        }
188
189        [RubyMethod("clr_ctor")]
190        [RubyMethod("clr_constructor")]
191        public static RubyMethod/*!*/ GetClrConstructor(RubyContext/*!*/ context, TypeGroup/*!*/ self) {
192            return ClassOps.GetClrConstructor(GetNonGenericClass(context, self));
193        }
194    }
195}