コード例 #1
0
ファイル: Runtime.cs プロジェクト: modulexcite/IL2JS
 public NullableInteropOps(Runtime outer, Type type, TypeInfo typeInfo)
     : base(outer, type, typeInfo)
 {
     var elemType = TypeInfo.ExplodeNullableType(type);
     if (elemType == null)
         throw new InvalidOperationException("not a nullable type");
     elemInteropOps = outer.FindInteropOps(elemType);
 }
コード例 #2
0
ファイル: Runtime.cs プロジェクト: modulexcite/IL2JS
        // ----------------------------------------------------------------------
        // Imported and Exported methods
        // ----------------------------------------------------------------------

        // Called from body of imported method to redirect to imported method. Method is (possibly an instance
        // of a polymorphic method) in (possibly an instance of a higher kinded) type.
        // If method is a constructor:
        //  - the uninitialized managed object has already been created, but is NOT passed as first
        //    argument in args, and is not represented in argTypes.
        //  - function on unmanaged side does not expect any 'this' argument, but will instead create, initialize
        //    and return the new unmanaged object.
        //  - we return a JSContext for the newly created unamanged object
        //  - the calling ctor must then call the best-matching 'importing constructor' to initialize the
        //    managed object, then call CompleteConstruction to associate the managed and unmanaged objects.
        public object CallImportedMethod(SimpleMethodBase methodBase, string script, params object[] args)
        {
            var resType = default(Type);
            var argTypes = TypeInfo.ExplodeSimpleMethodBase(methodBase, out resType);
            var argInteropOps = new InteropOps[argTypes.Count];
            for (var i = 0; i < argTypes.Count; i++)
                argInteropOps[i] = FindInteropOps(argTypes[i]);
            var resInteropOps = resType == null ? null : FindInteropOps(resType);

            if (args.Length != argInteropOps.Length)
                throw new InvalidOperationException("mismatched method arity");

            // First pass: check if we need to create any Proxied or Keyed counterparts for arguments, and/or
            //             bind any exported instance methods into unmanaged counterpart.
            for (var i = 0; i < args.Length; i++)
            {
                if (argInteropOps[i].NeedsCreate(args[i]))
                    Eval(argInteropOps[i].AppendCreate, sp => argInteropOps[i].BindCreatedInstance(sp, args[i]));
                if (argInteropOps[i].NeedsInstanceExportsBound(args[i]))
                    BindExportedMethodsOfType(args[i].GetType(), args[i]);
            }
            // Second pass: export args, make call, import result
            Action<StringBuilder, Dictionary<Type, int>> makeCall = (sb, toBeLoaded) =>
                                                                    {
                                                                        sb.Append('(');
                                                                        sb.Append(script);
                                                                        sb.Append(")(");
                                                                        for (var i = 0; i < args.Length; i++)
                                                                        {
                                                                            if (i > 0)
                                                                                sb.Append(',');
                                                                            argInteropOps[i].AppendExport
                                                                                (sb, toBeLoaded, args[i]);
                                                                        }
                                                                        sb.Append(')');
                                                                        if (resType == null)
                                                                            sb.Append(';');
                                                                    };
            if (resType == null)
                return Eval(makeCall, null);
            else
                return Eval
                    (resInteropOps.WrapImport(makeCall),
                     sp =>
                     {
                         sp.SkipWS();
                         if (methodBase is SimpleConstructorInfo)
                             return resInteropOps.ContextForUnmanagedInstance(sp);
                         else
                             return resInteropOps.Import(sp);
                     });
        }
コード例 #3
0
ファイル: Runtime.cs プロジェクト: modulexcite/IL2JS
        public void BindExportedMethod(MethodBase methodBase, object obj, string script)
        {
            if (obj != null)
            {
                // Method is a monomorphic instance method of a (possibly higher-kinded) type. Use the type of 
                // the instance to recover the type at which the higher-kinded type is instantiated, and find
                // the fully instantiated method base to invoke. Remember, the instance may be a subtype of the
                // method's declaring type.
                var fkObjType = obj.GetType();
                var hkMethodType = methodBase.DeclaringType;
                while (true)
                {
                    var classTypeArguments = fkObjType.GetGenericArguments();
                    var hkObjType = fkObjType;
                    if (classTypeArguments.Length > 0)
                        hkObjType = fkObjType.GetGenericTypeDefinition();
                    if (hkObjType.Equals(hkMethodType))
                    {
                        if (classTypeArguments.Length != hkMethodType.GetGenericArguments().Length)
                            throw new InvalidOperationException("mismatched type arities");
                        methodBase = TypeInfo.FindMethodBase(hkMethodType, classTypeArguments, methodBase);
                        break;
                    }
                    fkObjType = fkObjType.BaseType;
                    if (fkObjType == null)
                        throw new InvalidOperationException
                            ("object type is not a subtype of method's declaring type");
                }
            }

            var id = default(int);
            if (!exportedMethodBaseToId.TryGetValue(methodBase, out id))
            {
                id = nextObjectId++;
                exportedMethodBaseToId.Add(methodBase, id);
                idToExportedMethodBase.Add(id, methodBase);
            }
            var resType = default(Type);
            var argTypes = TypeInfo.ExplodeMethodBase(methodBase, out resType);
            var argInteropOps = new InteropOps[argTypes.Count];
            for (var i = 0; i < argTypes.Count; i++)
                argInteropOps[i] = FindInteropOps(argTypes[i]);

            // First pass: check if instance object needs to have a Keyed or Proxied counterpart created
            if (obj != null)
            {
                if (methodBase.IsStatic || methodBase is ConstructorInfo)
                    throw new InvalidOperationException("no instance expected for static methods and constructors");
                if (argInteropOps[0].NeedsCreate(obj))
                    Eval(argInteropOps[0].AppendCreate, sp => argInteropOps[0].BindCreatedInstance(sp, obj));
            }

            Eval
                ((sb, toBeLoaded) =>
                 {
                     sb.Append('(');
                     sb.Append(script);
                     sb.Append(")(");
                     if (obj != null)
                     {
                         argInteropOps[0].AppendExport(sb, toBeLoaded, obj);
                         sb.Append(',');
                     }
                     sb.Append(database.RootExpression);
                     sb.Append(".MakeExportRedirector([");
                     // If method is a constructor:
                     //  - function on unmanaged side will be called without the first 'this' argument,
                     //  - CallManaged (above) must create the object itself, call the constructor, and return
                     //    the object
                     //  - function on unmanaged side should return constructed object
                     for (var i = 0; i < argTypes.Count; i++)
                     {
                         if (i > 0)
                             sb.Append(',');
                         sb.Append(TypeIndex(toBeLoaded, argTypes[i]));
                     }
                     sb.Append("],");
                     sb.Append(id);
                     sb.Append(",false,false));");
                 },
                 null);
        }
コード例 #4
0
ファイル: Runtime.cs プロジェクト: modulexcite/IL2JS
 public DelegateInteropOps(Runtime outer, Type type, TypeInfo typeInfo)
     : base(outer, type, typeInfo)
 {
     var resType = default(Type);
     var argTypes = TypeInfo.ExplodeDelegateType(type, out resType);
     if (argTypes == null)
         throw new InvalidOperationException("not a delegate type");
     argInteropOps = new InteropOps[argTypes.Count];
     for (var i = 0; i < argTypes.Count; i++)
         argInteropOps[i] = outer.FindInteropOps(argTypes[i]);
     resInteropOps = resType == null ? null : outer.FindInteropOps(resType);
     captureThis = typeInfo.CaptureThis;
     inlineParamsArray = typeInfo.InlineParamsArray;
 }