예제 #1
0
        public void EmitField(DecompilerContext context, IAstEmitter astEmitter, FieldDefinition field, JSRawOutputIdentifier dollar, JSExpression defaultValue)
        {
            var fieldInfo = Translator.TypeInfoProvider.GetField(field);
            var typeKeyword = WasmUtil.PickTypeKeyword(fieldInfo.FieldType);

            // Unhandled type
            if (typeKeyword == null)
                return;

            Switch(PrecedingType.Global);

            Formatter.WriteRaw("(global ${0} {1})", WasmUtil.EscapeIdentifier(fieldInfo.Name), typeKeyword);
            Formatter.ConditionalNewLine();
        }
예제 #2
0
 public void EmitCachedValues(IAstEmitter astEmitter, TypeExpressionCacher typeCacher, SignatureCacher signatureCacher, BaseMethodCacher baseMethodCacher)
 {
 }
예제 #3
0
 public bool EmitTypeDeclarationHeader(DecompilerContext context, IAstEmitter astEmitter, TypeDefinition typedef, TypeInfo typeInfo)
 {
     return(true);
 }
예제 #4
0
        public void BeginEmitTypeDefinition(
            IAstEmitter astEmitter,
            TypeDefinition typedef, TypeInfo typeInfo,
            TypeReference baseClass
            )
        {
            Formatter.NewLine();

            bool isStaticClass = typedef.IsAbstract && typedef.IsSealed;

            if (isStaticClass)
            {
                Formatter.Identifier("JSIL.MakeStaticClass", EscapingMode.None);
                Formatter.LPar();

                Formatter.Value(Util.DemangleCecilTypeName(typeInfo.FullName));
                Formatter.Comma();
                Formatter.Value(typedef.IsPublic);

                Formatter.Comma();
                Formatter.OpenBracket();
                if (typedef.HasGenericParameters)
                {
                    WriteGenericParameterNames(typedef.GenericParameters);
                }
                Formatter.CloseBracket();
            }
            else
            {
                Formatter.Identifier("JSIL.MakeType", EscapingMode.None);

                Formatter.LPar();
                Formatter.OpenBrace();

                Formatter.WriteRaw("BaseType: ");

                if (baseClass == null)
                {
                    if (typedef.FullName != "System.Object")
                    {
                        throw new InvalidDataException(String.Format(
                                                           "Type '{0}' has no base class and isn't System.Object.",
                                                           typedef.FullName
                                                           ));
                    }

                    Formatter.Identifier("$jsilcore");
                    Formatter.Dot();
                    Formatter.Identifier("TypeRef");
                    Formatter.LPar();
                    Formatter.Value("System.Object");
                    Formatter.RPar();
                }
                else if (typedef.FullName == "System.ValueType")
                {
                    Formatter.Identifier("$jsilcore");
                    Formatter.Dot();
                    Formatter.Identifier("TypeRef");
                    Formatter.LPar();
                    Formatter.Value("System.ValueType");
                    Formatter.RPar();
                }
                else
                {
                    Formatter.TypeReference(baseClass, astEmitter.ReferenceContext);
                }

                Formatter.Comma();
                Formatter.NewLine();

                Formatter.WriteRaw("Name: ");
                Formatter.Value(Util.DemangleCecilTypeName(typeInfo.FullName));
                Formatter.Comma();
                Formatter.NewLine();

                Formatter.WriteRaw("IsPublic: ");
                Formatter.Value(typedef.IsPublic);
                Formatter.Comma();
                Formatter.NewLine();

                Formatter.WriteRaw("IsReferenceType: ");
                Formatter.Value(!typedef.IsValueType);
                Formatter.Comma();
                Formatter.NewLine();

                if (typedef.HasGenericParameters)
                {
                    Formatter.WriteRaw("GenericParameters: ");
                    Formatter.OpenBracket();
                    WriteGenericParameterNames(typedef.GenericParameters);
                    Formatter.CloseBracket();
                    Formatter.Comma();
                    Formatter.NewLine();
                }

                var constructors = typedef.Methods.Where((m) => m.IsConstructor).ToList();
                if ((constructors.Count != 0) || typedef.IsValueType)
                {
                    Formatter.WriteRaw("MaximumConstructorArguments: ");

                    if (typedef.IsValueType && (constructors.Count == 0))
                    {
                        Formatter.Value(0);
                    }
                    else
                    {
                        Formatter.Value(constructors.Max((m) => m.Parameters.Count));
                    }

                    Formatter.Comma();
                    Formatter.NewLine();
                }

                if (typedef.IsExplicitLayout)
                {
                    Formatter.WriteRaw("ExplicitLayout: true");
                    Formatter.Comma();
                    Formatter.NewLine();
                }
                else if (typedef.IsSequentialLayout)
                {
                    Formatter.WriteRaw("SequentialLayout: true");
                    Formatter.Comma();
                    Formatter.NewLine();
                }

                if (typedef.HasLayoutInfo)
                {
                    if (typedef.PackingSize != 0)
                    {
                        Formatter.WriteRaw("Pack: ");
                        Formatter.Value(typedef.PackingSize);
                        Formatter.Comma();
                        Formatter.NewLine();
                    }

                    if (typedef.ClassSize != 0)
                    {
                        Formatter.WriteRaw("SizeBytes: ");
                        Formatter.Value(typedef.ClassSize);
                        Formatter.Comma();
                        Formatter.NewLine();
                    }
                }

                Formatter.CloseBrace(false);
            }

            // Hack to force the indent level for type definitions to be 1 instead of 2.
            Formatter.Unindent();

            Formatter.Comma();
            Formatter.OpenFunction(null, (f) =>
                                   f.Identifier("$ib")
                                   );

            Formatter.WriteRaw("$ = $ib;");
            Formatter.NewLine();

            astEmitter.ReferenceContext.Push();
            astEmitter.ReferenceContext.EnclosingType = typedef;
        }
예제 #5
0
        public bool EmitTypeDeclarationHeader (DecompilerContext context, IAstEmitter astEmitter, TypeDefinition typedef, TypeInfo typeInfo) {
            Formatter.DeclareNamespace(typedef.Namespace);

            if (typeInfo.IsExternal) {
                Formatter.Identifier("JSIL.MakeExternalType", EscapingMode.None);
                Formatter.LPar();

                Formatter.Value(Util.DemangleCecilTypeName(typeInfo.FullName));
                Formatter.Comma();
                Formatter.Value(typedef.IsPublic);

                Formatter.RPar();
                Formatter.Semicolon();
                Formatter.NewLine();
                return false;
            } else if (typedef.IsInterface) {
                Formatter.Comment("interface {0}", Util.DemangleCecilTypeName(typedef.FullName));
                Formatter.NewLine();
                Formatter.NewLine();

                EmitInterfaceDefinition(context, astEmitter, typedef);
                return false;
            } else if (typedef.IsEnum) {
                Formatter.Comment("enum {0}", Util.DemangleCecilTypeName(typedef.FullName));
                Formatter.NewLine();
                Formatter.NewLine();

                EmitEnum(context, typedef, astEmitter);
                return false;
            } else if (typeInfo.IsDelegate) {
                Formatter.Comment("delegate {0}", Util.DemangleCecilTypeName(typedef.FullName));
                Formatter.NewLine();
                Formatter.NewLine();

                EmitDelegate(context, typedef, typeInfo, astEmitter);
                return false;
            }

            return true;
        }
예제 #6
0
        private void EmitPInvokeInfo (
            MethodReference methodRef, MethodDefinition method, 
            IAstEmitter astEmitter
        ) {
            var pii = method.PInvokeInfo;

            Formatter.OpenBrace();

            if (pii != null) {
                Formatter.WriteRaw("Module: ");
                Formatter.Value(pii.Module.Name);
                Formatter.Comma();
                Formatter.NewLine();

                if (pii.IsCharSetAuto) {
                    Formatter.WriteRaw("CharSet: 'auto',");
                    Formatter.NewLine();
                } else if (pii.IsCharSetUnicode) {
                    Formatter.WriteRaw("CharSet: 'unicode',");
                    Formatter.NewLine();
                } else if (pii.IsCharSetAnsi) {
                    Formatter.WriteRaw("CharSet: 'ansi',");
                    Formatter.NewLine();
                }

                if ((pii.EntryPoint != null) && (pii.EntryPoint != method.Name)) {
                    Formatter.WriteRaw("EntryPoint: ");
                    Formatter.Value(pii.EntryPoint);
                    Formatter.Comma();
                    Formatter.NewLine();
                }
            }

            bool isArgsDictOpen = false;

            foreach (var p in method.Parameters) {
                if (p.HasMarshalInfo) {
                    if (!isArgsDictOpen) {
                        isArgsDictOpen = true;
                        Formatter.WriteRaw("Parameters: ");
                        Formatter.OpenBracket(true);
                    } else {
                        Formatter.Comma();
                        Formatter.NewLine();
                    }

                    EmitMarshalInfo(
                        methodRef, method,
                        p.Attributes, p.MarshalInfo, 
                        astEmitter
                    );
                } else if (isArgsDictOpen) {
                    Formatter.WriteRaw(", null");
                    Formatter.NewLine();
                }
            }

            if (isArgsDictOpen)
                Formatter.CloseBracket(true);

            if (method.MethodReturnType.HasMarshalInfo) {
                if (isArgsDictOpen)
                    Formatter.Comma();

                Formatter.WriteRaw("Result: ");

                EmitMarshalInfo(
                    methodRef, method,
                    method.MethodReturnType.Attributes, method.MethodReturnType.MarshalInfo, 
                    astEmitter
                );
                Formatter.NewLine();
            }

            Formatter.CloseBrace(false);
        }
예제 #7
0
        public void EmitCustomAttributes (
            DecompilerContext context, 
            TypeReference declaringType,
            ICustomAttributeProvider member, 
            IAstEmitter astEmitter, 
            bool standalone = true
        ) {
            astEmitter.ReferenceContext.Push();
            try {
                astEmitter.ReferenceContext.EnclosingType = null;
                astEmitter.ReferenceContext.DefiningType = null;

                if (standalone)
                    Formatter.Indent();

                bool isFirst = true;

                foreach (var attribute in member.CustomAttributes) {
                    if (Translator.ShouldSkipMember(attribute.AttributeType))
                        continue;

                    // Don't emit Meta attributes into the output JS
                    if (attribute.AttributeType.Namespace == "JSIL.Meta")
                        continue;

                    if (!isFirst || standalone)
                        Formatter.NewLine();
                        
                    Formatter.Dot();
                    Formatter.Identifier("Attribute");
                    Formatter.LPar();
                    Formatter.TypeReference(attribute.AttributeType, astEmitter.ReferenceContext);

                    var constructorArgs = attribute.ConstructorArguments.ToArray();
                    if (constructorArgs.Length > 0) {
                        Formatter.Comma();

                        Formatter.WriteRaw("function () { return ");
                        Formatter.OpenBracket(false);
                        // FIXME: Get rid of this gross cast
                        ((JavascriptAstEmitter)astEmitter).CommaSeparatedList(
                            (from ca in constructorArgs
                             select TranslateAttributeConstructorArgument(
                                astEmitter.TypeSystem, declaringType, ca
                             ))
                        );
                        Formatter.CloseBracket(false);
                        Formatter.WriteRaw("; }");
                    }

                    Formatter.RPar();

                    isFirst = false;
                }

                if (standalone)
                    Formatter.Unindent();
            } finally {
                astEmitter.ReferenceContext.Pop();
            }
        }
예제 #8
0
        public void EmitCachedValues (IAstEmitter astEmitter, TypeExpressionCacher typeCacher, SignatureCacher signatureCacher, BaseMethodCacher baseMethodCacher) {
            var cts = typeCacher.CachedTypes.Values.OrderBy((ct) => ct.Index).ToArray();
            if (cts.Length > 0) {
                foreach (var ct in cts) {
                    Formatter.WriteRaw("var $T{0:X2} = function () ", ct.Index);
                    Formatter.OpenBrace();
                    Formatter.WriteRaw("return ($T{0:X2} = JSIL.Memoize(", ct.Index);
                    Formatter.Identifier(ct.Type, astEmitter.ReferenceContext, false);
                    Formatter.WriteRaw(")) ()");
                    Formatter.Semicolon(true);
                    Formatter.CloseBrace(false);
                    Formatter.Semicolon(true);
                }
            }

            var css = signatureCacher.Global.Signatures.OrderBy((cs) => cs.Value).ToArray();
            if (css.Length > 0) {
                foreach (var cs in css) {
                    if (cs.Key.RewritenGenericParametersCount == 0)
                    {
                        Formatter.WriteRaw("var $S{0:X2} = function () ", cs.Value);
                        Formatter.OpenBrace();
                        Formatter.WriteRaw("return ($S{0:X2} = JSIL.Memoize(", cs.Value);
                        Formatter.Signature(cs.Key.Method, cs.Key.Signature, astEmitter.ReferenceContext,
                            cs.Key.IsConstructor, false, true);
                        Formatter.WriteRaw(")) ()");
                        Formatter.Semicolon(true);
                        Formatter.CloseBrace(false);
                        Formatter.Semicolon(true);
                    }
                    else
                    {
                        Formatter.WriteRaw("var $S{0:X2} = function ", cs.Value);
                        Formatter.LPar();
                        Formatter.CommaSeparatedList(
                            Enumerable.Range(1, cs.Key.RewritenGenericParametersCount).Select(item => "arg" + item),
                            astEmitter.ReferenceContext,
                            ListValueType.Raw);
                        Formatter.RPar();
                        Formatter.Space();

                        Formatter.OpenBrace();
                        Formatter.WriteRaw("return JSIL.MemoizeTypes($S{0:X2}, function() {{return ", cs.Value);
                        Formatter.Signature(cs.Key.Method, cs.Key.Signature, astEmitter.ReferenceContext,
                            cs.Key.IsConstructor, false, true);
                        Formatter.WriteRaw(";}");
                        Formatter.Comma();
                        Formatter.OpenBracket();
                        Formatter.CommaSeparatedList(
                            Enumerable.Range(1, cs.Key.RewritenGenericParametersCount).Select(item => "arg" + item),
                            astEmitter.ReferenceContext,
                            ListValueType.Raw);
                        Formatter.CloseBracket();
                        Formatter.WriteRaw(")");
                        Formatter.Semicolon(true);
                        Formatter.CloseBrace(false);
                        Formatter.Semicolon(true);
                    }
                }
            }

            var bms = baseMethodCacher.CachedMethods.Values.OrderBy((ct) => ct.Index).ToArray();
            if (bms.Length > 0) {
                foreach (var bm in bms) {
                    Formatter.WriteRaw("var $BM{0:X2} = function () ", bm.Index);
                    Formatter.OpenBrace();
                    Formatter.WriteRaw("return ($BM{0:X2} = JSIL.Memoize(", bm.Index);
                    Formatter.WriteRaw("Function.call.bind(");
                    Formatter.Identifier(bm.Method.Reference, astEmitter.ReferenceContext, true);
                    Formatter.WriteRaw("))) ()");
                    Formatter.Semicolon(true);
                    Formatter.CloseBrace(false);
                    Formatter.Semicolon(true);
                }
            }

            var cims = signatureCacher.Global.InterfaceMembers.OrderBy((cim) => cim.Value).ToArray();
            if (cims.Length > 0) {
                foreach (var cim in cims) {
                    if (cim.Key.RewritenGenericParametersCount == 0)
                    {
                        Formatter.WriteRaw("var $IM{0:X2} = function () ", cim.Value);
                        Formatter.OpenBrace();
                        Formatter.WriteRaw("return ($IM{0:X2} = JSIL.Memoize(", cim.Value);
                        Formatter.Identifier(cim.Key.InterfaceType, astEmitter.ReferenceContext, false);
                        Formatter.Dot();
                        Formatter.Identifier(cim.Key.InterfaceMember, EscapingMode.MemberIdentifier);
                        Formatter.WriteRaw(")) ()");
                        Formatter.Semicolon(true);
                        Formatter.CloseBrace(false);
                        Formatter.Semicolon(true);
                    }
                    else
                    {
                        Formatter.WriteRaw("var $IM{0:X2} = function ", cim.Value);
                        Formatter.LPar();
                        Formatter.CommaSeparatedList(
                            Enumerable.Range(1, cim.Key.RewritenGenericParametersCount).Select(item => "arg" + item),
                            astEmitter.ReferenceContext,
                            ListValueType.Raw);
                        Formatter.RPar();
                        Formatter.Space();

                        Formatter.OpenBrace();
                        Formatter.WriteRaw("return JSIL.MemoizeTypes($IM{0:X2}, function() {{return ", cim.Value);
                        Formatter.Identifier(cim.Key.InterfaceType, astEmitter.ReferenceContext, false);
                        Formatter.Dot();
                        Formatter.Identifier(cim.Key.InterfaceMember, EscapingMode.MemberIdentifier);
                        Formatter.WriteRaw(";}");
                        Formatter.Comma();
                        Formatter.OpenBracket();
                        Formatter.CommaSeparatedList(
                            Enumerable.Range(1, cim.Key.RewritenGenericParametersCount).Select(item => "arg" + item),
                            astEmitter.ReferenceContext,
                            ListValueType.Raw);
                        Formatter.CloseBracket();
                        Formatter.WriteRaw(")");
                        Formatter.Semicolon(true);
                        Formatter.CloseBrace(false);
                        Formatter.Semicolon(true);
                    }
                }
            }

            if ((cts.Length > 0) || (css.Length > 0))
                Formatter.NewLine();
        }
예제 #9
0
        protected void EmitDelegate(DecompilerContext context, TypeDefinition del, TypeInfo typeInfo, IAstEmitter astEmitter)
        {
            Formatter.Identifier("JSIL.MakeDelegate", EscapingMode.None);
            Formatter.LPar();

            Formatter.Value(Util.DemangleCecilTypeName(del.FullName));
            Formatter.Comma();

            Formatter.Value(del.IsPublic);

            Formatter.Comma();
            Formatter.OpenBracket();
            if (del.HasGenericParameters)
            {
                WriteGenericParameterNames(del.GenericParameters);
            }
            Formatter.CloseBracket();

            var invokeMethod = del.Methods.FirstOrDefault(method => method.Name == "Invoke");

            if (invokeMethod != null)
            {
                Formatter.Comma();
                Formatter.NewLine();

                astEmitter.ReferenceContext.Push();
                astEmitter.ReferenceContext.DefiningType = del;
                try
                {
                    Formatter.MethodSignature(invokeMethod,
                                              typeInfo.MethodSignatures.GetOrCreateFor("Invoke").First(),
                                              astEmitter.ReferenceContext);
                }
                finally
                {
                    astEmitter.ReferenceContext.Pop();
                }

                if (
                    invokeMethod.HasPInvokeInfo ||
                    invokeMethod.MethodReturnType.HasMarshalInfo ||
                    invokeMethod.Parameters.Any(p => p.HasMarshalInfo)
                    )
                {
                    Formatter.Comma();
                    EmitPInvokeInfo(invokeMethod, invokeMethod, astEmitter);
                    Formatter.NewLine();
                }
            }

            Formatter.RPar();
            Formatter.Semicolon();
            Formatter.NewLine();
        }
예제 #10
0
        private void EmitPInvokeInfo(
            MethodReference methodRef, MethodDefinition method,
            IAstEmitter astEmitter
            )
        {
            var pii = method.PInvokeInfo;

            Formatter.OpenBrace();

            if (pii != null)
            {
                Formatter.WriteRaw("Module: ");
                Formatter.Value(pii.Module.Name);
                Formatter.Comma();
                Formatter.NewLine();

                if (pii.IsCharSetAuto)
                {
                    Formatter.WriteRaw("CharSet: 'auto',");
                    Formatter.NewLine();
                }
                else if (pii.IsCharSetUnicode)
                {
                    Formatter.WriteRaw("CharSet: 'unicode',");
                    Formatter.NewLine();
                }
                else if (pii.IsCharSetAnsi)
                {
                    Formatter.WriteRaw("CharSet: 'ansi',");
                    Formatter.NewLine();
                }

                if ((pii.EntryPoint != null) && (pii.EntryPoint != method.Name))
                {
                    Formatter.WriteRaw("EntryPoint: ");
                    Formatter.Value(pii.EntryPoint);
                    Formatter.Comma();
                    Formatter.NewLine();
                }
            }

            bool isArgsDictOpen = false;

            foreach (var p in method.Parameters)
            {
                if (p.HasMarshalInfo)
                {
                    if (!isArgsDictOpen)
                    {
                        isArgsDictOpen = true;
                        Formatter.WriteRaw("Parameters: ");
                        Formatter.OpenBracket(true);
                    }
                    else
                    {
                        Formatter.Comma();
                        Formatter.NewLine();
                    }

                    EmitMarshalInfo(
                        methodRef, method,
                        p.Attributes, p.MarshalInfo,
                        astEmitter
                        );
                }
                else if (isArgsDictOpen)
                {
                    Formatter.WriteRaw(", null");
                    Formatter.NewLine();
                }
            }

            if (isArgsDictOpen)
            {
                Formatter.CloseBracket(true);
            }

            if (method.MethodReturnType.HasMarshalInfo)
            {
                if (isArgsDictOpen)
                {
                    Formatter.Comma();
                }

                Formatter.WriteRaw("Result: ");

                EmitMarshalInfo(
                    methodRef, method,
                    method.MethodReturnType.Attributes, method.MethodReturnType.MarshalInfo,
                    astEmitter
                    );
                Formatter.NewLine();
            }

            Formatter.CloseBrace(false);
        }
예제 #11
0
        public void EmitMethodDefinition(
            DecompilerContext context, MethodReference methodRef, MethodDefinition method,
            IAstEmitter astEmitter, bool stubbed,
            JSRawOutputIdentifier dollar, MethodInfo methodInfo = null
            )
        {
            if (methodInfo == null)
            {
                methodInfo = _TypeInfoProvider.GetMemberInformation <Internal.MethodInfo>(method);
            }

            bool isExternal, isReplaced, methodIsProxied;

            if (!Translator.ShouldTranslateMethodBody(
                    method, methodInfo, stubbed,
                    out isExternal, out isReplaced, out methodIsProxied
                    ))
            {
                return;
            }

            JSFunctionExpression function = Translator.GetFunctionBodyForMethod(
                isExternal, methodInfo
                );

            astEmitter.ReferenceContext.EnclosingType   = method.DeclaringType;
            astEmitter.ReferenceContext.EnclosingMethod = null;

            Formatter.NewLine();

            astEmitter.ReferenceContext.Push();
            astEmitter.ReferenceContext.DefiningMethod = methodRef;

            try {
                dollar.WriteTo(Formatter);
                Formatter.Dot();
                if (methodInfo.IsPInvoke)
                {
                    // FIXME: Write out dll name from DllImport
                    // FIXME: Write out alternate method name if provided
                    Formatter.Identifier("PInvokeMethod", EscapingMode.None);
                }
                else if (isExternal && !Configuration.GenerateSkeletonsForStubbedAssemblies.GetValueOrDefault(false))
                {
                    Formatter.Identifier("ExternalMethod", EscapingMode.None);
                }
                else
                {
                    Formatter.Identifier("Method", EscapingMode.None);
                }
                Formatter.LPar();

                // FIXME: Include IsVirtual?
                Formatter.MemberDescriptor(method.IsPublic, method.IsStatic, method.IsVirtual, false);

                Formatter.Comma();
                Formatter.Value(Util.EscapeIdentifier(methodInfo.GetName(true), EscapingMode.String));

                Formatter.Comma();
                Formatter.NewLine();

                Formatter.MethodSignature(methodRef, methodInfo.Signature, astEmitter.ReferenceContext);

                if (methodInfo.IsPInvoke && method.HasPInvokeInfo)
                {
                    Formatter.Comma();
                    Formatter.NewLine();
                    EmitPInvokeInfo(
                        methodRef, method, astEmitter
                        );
                }
                else if (!isExternal)
                {
                    Formatter.Comma();
                    Formatter.NewLine();

                    if (function != null)
                    {
                        Formatter.WriteRaw(Util.EscapeIdentifier(function.DisplayName));
                    }
                    else
                    {
                        Formatter.Identifier("JSIL.UntranslatableFunction", EscapingMode.None);
                        Formatter.LPar();
                        Formatter.Value(method.FullName);
                        Formatter.RPar();
                    }
                }

                Formatter.NewLine();
                Formatter.RPar();

                astEmitter.ReferenceContext.AttributesMethod = methodRef;

                EmitOverrides(context, methodInfo.DeclaringType, method, methodInfo, astEmitter);

                EmitCustomAttributes(context, method.DeclaringType, method, astEmitter);

                EmitParameterAttributes(context, method.DeclaringType, method, astEmitter);

                Formatter.Semicolon();
            } finally {
                astEmitter.ReferenceContext.Pop();
            }
        }
예제 #12
0
        public void EmitCustomAttributes(
            DecompilerContext context,
            TypeReference declaringType,
            ICustomAttributeProvider member,
            IAstEmitter astEmitter,
            bool standalone = true
            )
        {
            astEmitter.ReferenceContext.Push();
            try {
                astEmitter.ReferenceContext.EnclosingType = null;
                astEmitter.ReferenceContext.DefiningType  = null;

                if (standalone)
                {
                    Formatter.Indent();
                }

                bool isFirst = true;

                foreach (var attribute in member.CustomAttributes)
                {
                    if (Translator.ShouldSkipMember(attribute.AttributeType))
                    {
                        continue;
                    }

                    if (!isFirst || standalone)
                    {
                        Formatter.NewLine();
                    }

                    Formatter.Dot();
                    Formatter.Identifier("Attribute");
                    Formatter.LPar();
                    Formatter.TypeReference(attribute.AttributeType, astEmitter.ReferenceContext);

                    var constructorArgs = attribute.ConstructorArguments.ToArray();
                    if (constructorArgs.Length > 0)
                    {
                        Formatter.Comma();

                        Formatter.WriteRaw("function () { return ");
                        Formatter.OpenBracket(false);
                        // FIXME: Get rid of this gross cast
                        ((JavascriptAstEmitter)astEmitter).CommaSeparatedList(
                            (from ca in constructorArgs
                             select TranslateAttributeConstructorArgument(
                                 astEmitter.TypeSystem, declaringType, ca
                                 ))
                            );
                        Formatter.CloseBracket(false);
                        Formatter.WriteRaw("; }");
                    }

                    Formatter.RPar();

                    isFirst = false;
                }

                if (standalone)
                {
                    Formatter.Unindent();
                }
            } finally {
                astEmitter.ReferenceContext.Pop();
            }
        }
예제 #13
0
 public void EmitField(DecompilerContext context, IAstEmitter astEmitter, FieldDefinition field, JSRawOutputIdentifier dollar, JSExpression defaultValue)
 {
     EmitFieldOrConstant(context, astEmitter, field, dollar, defaultValue, false);
 }
예제 #14
0
        public void EmitCachedValues(IAstEmitter astEmitter, TypeExpressionCacher typeCacher, SignatureCacher signatureCacher, BaseMethodCacher baseMethodCacher)
        {
            var cts = typeCacher.CachedTypes.Values.OrderBy((ct) => ct.Index).ToArray();

            if (cts.Length > 0)
            {
                foreach (var ct in cts)
                {
                    Formatter.WriteRaw("var $T{0:X2} = function () ", ct.Index);
                    Formatter.OpenBrace();
                    Formatter.WriteRaw("return ($T{0:X2} = JSIL.Memoize(", ct.Index);
                    Formatter.Identifier(ct.Type, astEmitter.ReferenceContext, false);
                    Formatter.WriteRaw(")) ()");
                    Formatter.Semicolon(true);
                    Formatter.CloseBrace(false);
                    Formatter.Semicolon(true);
                }
            }

            var css = signatureCacher.Global.Signatures.OrderBy((cs) => cs.Value).ToArray();

            if (css.Length > 0)
            {
                foreach (var cs in css)
                {
                    Formatter.WriteRaw("var $S{0:X2} = function () ", cs.Value);
                    Formatter.OpenBrace();
                    Formatter.WriteRaw("return ($S{0:X2} = JSIL.Memoize(", cs.Value);
                    Formatter.Signature(cs.Key.Method, cs.Key.Signature, astEmitter.ReferenceContext, cs.Key.IsConstructor, false);
                    Formatter.WriteRaw(")) ()");
                    Formatter.Semicolon(true);
                    Formatter.CloseBrace(false);
                    Formatter.Semicolon(true);
                }
            }

            var bms = baseMethodCacher.CachedMethods.Values.OrderBy((ct) => ct.Index).ToArray();

            if (bms.Length > 0)
            {
                foreach (var bm in bms)
                {
                    Formatter.WriteRaw("var $BM{0:X2} = function () ", bm.Index);
                    Formatter.OpenBrace();
                    Formatter.WriteRaw("return ($BM{0:X2} = JSIL.Memoize(", bm.Index);
                    Formatter.WriteRaw("Function.call.bind(");
                    Formatter.Identifier(bm.Method.Reference, astEmitter.ReferenceContext, true);
                    Formatter.WriteRaw("))) ()");
                    Formatter.Semicolon(true);
                    Formatter.CloseBrace(false);
                    Formatter.Semicolon(true);
                }
            }

            var cims = signatureCacher.Global.InterfaceMembers.OrderBy((cim) => cim.Value).ToArray();

            if (cims.Length > 0)
            {
                foreach (var cim in cims)
                {
                    Formatter.WriteRaw("var $IM{0:X2} = function () ", cim.Value);
                    Formatter.OpenBrace();
                    Formatter.WriteRaw("return ($IM{0:X2} = JSIL.Memoize(", cim.Value);
                    Formatter.Identifier(cim.Key.InterfaceType, astEmitter.ReferenceContext, false);
                    Formatter.Dot();
                    Formatter.Identifier(cim.Key.InterfaceMember, EscapingMode.MemberIdentifier);
                    Formatter.WriteRaw(")) ()");
                    Formatter.Semicolon(true);
                    Formatter.CloseBrace(false);
                    Formatter.Semicolon(true);
                }
            }

            if ((cts.Length > 0) || (css.Length > 0))
            {
                Formatter.NewLine();
            }
        }
예제 #15
0
        public void EmitInterfaceDefinition(
            DecompilerContext context, IAstEmitter astEmitter, TypeDefinition iface
            )
        {
            Formatter.Identifier("JSIL.MakeInterface", EscapingMode.None);
            Formatter.LPar();
            Formatter.NewLine();

            Formatter.Value(Util.DemangleCecilTypeName(iface.FullName));
            Formatter.Comma();

            Formatter.Value(iface.IsPublic);
            Formatter.Comma();

            Formatter.OpenBracket();
            WriteGenericParameterNames(iface.GenericParameters);
            Formatter.CloseBracket();

            Formatter.Comma();
            Formatter.OpenFunction(null, (f) =>
                                   f.Identifier("$")
                                   );

            var refContext = new TypeReferenceContext {
                EnclosingType = iface,
                DefiningType  = iface
            };

            bool isFirst = true;

            foreach (var methodGroup in iface.Methods.GroupBy(md => md.Name))
            {
                foreach (var m in methodGroup)
                {
                    if (Translator.ShouldSkipMember(m))
                    {
                        continue;
                    }

                    var methodInfo = _TypeInfoProvider.GetMethod(m);

                    if ((methodInfo == null) || methodInfo.IsIgnored)
                    {
                        continue;
                    }

                    Formatter.Identifier("$", EscapingMode.None);
                    Formatter.Dot();
                    Formatter.Identifier("Method", EscapingMode.None);
                    Formatter.LPar();

                    Formatter.WriteRaw("{}");
                    Formatter.Comma();

                    Formatter.Value(Util.EscapeIdentifier(m.Name, EscapingMode.String));
                    Formatter.Comma();

                    Formatter.MethodSignature(m, methodInfo.Signature, refContext);

                    Formatter.RPar();
                    Formatter.Semicolon(true);
                }
            }

            foreach (var p in iface.Properties)
            {
                var propertyInfo = _TypeInfoProvider.GetProperty(p);
                if ((propertyInfo != null) && propertyInfo.IsIgnored)
                {
                    continue;
                }

                Formatter.Identifier("$", EscapingMode.None);
                Formatter.Dot();
                Formatter.Identifier("Property", EscapingMode.None);
                Formatter.LPar();

                Formatter.WriteRaw("{}");
                Formatter.Comma();

                Formatter.Value(Util.EscapeIdentifier(p.Name, EscapingMode.String));

                Formatter.RPar();
                Formatter.Semicolon(true);
            }

            Formatter.CloseBrace(false);

            Formatter.Comma();

            refContext = new TypeReferenceContext {
                EnclosingType = iface.DeclaringType,
                DefiningType  = iface
            };

            Formatter.OpenBracket();
            foreach (var i in iface.Interfaces)
            {
                if (!isFirst)
                {
                    Formatter.Comma();
                }

                Formatter.TypeReference(i, refContext);

                isFirst = false;
            }
            Formatter.CloseBracket();

            Formatter.RPar();

            EmitCustomAttributes(context, iface, iface, astEmitter);

            Formatter.Semicolon();
            Formatter.NewLine();
        }
예제 #16
0
        public void EmitCachedValues (IAstEmitter astEmitter, TypeExpressionCacher typeCacher, SignatureCacher signatureCacher, BaseMethodCacher baseMethodCacher) {
            var cts = typeCacher.CachedTypes.Values.OrderBy((ct) => ct.Index).ToArray();
            if (cts.Length > 0) {
                foreach (var ct in cts) {
                    Formatter.WriteRaw("var $T{0:X2} = function () ", ct.Index);
                    Formatter.OpenBrace();
                    Formatter.WriteRaw("return ($T{0:X2} = JSIL.Memoize(", ct.Index);
                    Formatter.Identifier(ct.Type, astEmitter.ReferenceContext, false);
                    Formatter.WriteRaw(")) ()");
                    Formatter.Semicolon(true);
                    Formatter.CloseBrace(false);
                    Formatter.Semicolon(true);
                }
            }

            var css = signatureCacher.Global.Signatures.OrderBy((cs) => cs.Value).ToArray();
            if (css.Length > 0) {
                foreach (var cs in css) {
                    Formatter.WriteRaw("var $S{0:X2} = function () ", cs.Value);
                    Formatter.OpenBrace();
                    Formatter.WriteRaw("return ($S{0:X2} = JSIL.Memoize(", cs.Value);
                    Formatter.Signature(cs.Key.Method, cs.Key.Signature, astEmitter.ReferenceContext, cs.Key.IsConstructor, false);
                    Formatter.WriteRaw(")) ()");
                    Formatter.Semicolon(true);
                    Formatter.CloseBrace(false);
                    Formatter.Semicolon(true);
                }
            }

            var bms = baseMethodCacher.CachedMethods.Values.OrderBy((ct) => ct.Index).ToArray();
            if (bms.Length > 0) {
                foreach (var bm in bms) {
                    Formatter.WriteRaw("var $BM{0:X2} = function () ", bm.Index);
                    Formatter.OpenBrace();
                    Formatter.WriteRaw("return ($BM{0:X2} = JSIL.Memoize(", bm.Index);
                    Formatter.WriteRaw("Function.call.bind(");
                    Formatter.Identifier(bm.Method.Reference, astEmitter.ReferenceContext, true);
                    Formatter.WriteRaw("))) ()");
                    Formatter.Semicolon(true);
                    Formatter.CloseBrace(false);
                    Formatter.Semicolon(true);
                }
            }

            var cims = signatureCacher.Global.InterfaceMembers.OrderBy((cim) => cim.Value).ToArray();
            if (cims.Length > 0) {
                foreach (var cim in cims) {
                    Formatter.WriteRaw("var $IM{0:X2} = function () ", cim.Value);
                    Formatter.OpenBrace();
                    Formatter.WriteRaw("return ($IM{0:X2} = JSIL.Memoize(", cim.Value);
                    Formatter.Identifier(cim.Key.InterfaceType, astEmitter.ReferenceContext, false);
                    Formatter.Dot();
                    Formatter.Identifier(cim.Key.InterfaceMember, EscapingMode.MemberIdentifier);
                    Formatter.WriteRaw(")) ()");
                    Formatter.Semicolon(true);
                    Formatter.CloseBrace(false);
                    Formatter.Semicolon(true);
                }
            }

            if ((cts.Length > 0) || (css.Length > 0))
                Formatter.NewLine();
        }
예제 #17
0
        public void EmitInterfaceList (
            TypeInfo typeInfo, 
            IAstEmitter astEmitter,
            JSRawOutputIdentifier dollar
        ) {
            var interfaces = typeInfo.AllInterfacesRecursive;
            if (interfaces.Count <= 0)
                return;

            Formatter.NewLine();

            dollar.WriteTo(Formatter);
            Formatter.Dot();
            Formatter.Identifier("ImplementInterfaces", EscapingMode.None);
            Formatter.LPar();

            bool firstInterface = true;

            for (var i = 0; i < interfaces.Count; i++) {
                var elt = interfaces.Array[interfaces.Offset + i];
                if (elt.ImplementingType != typeInfo)
                    continue;
                if (elt.ImplementedInterface.Info.IsIgnored)
                    continue;
                if (Translator.ShouldSkipMember(elt.ImplementedInterface.Reference))
                    continue;

                var @interface = elt.ImplementedInterface.Reference;

                if (firstInterface)
                    firstInterface = false;
                else
                    Formatter.Comma();

                Formatter.NewLine();

                Formatter.Comment("{0}", i);
                Formatter.TypeReference(@interface, astEmitter.ReferenceContext);
            }

            Formatter.NewLine();
            Formatter.RPar();
            Formatter.Semicolon(true);
        }
예제 #18
0
        public void EmitField(DecompilerContext context, IAstEmitter astEmitter, FieldDefinition field, JSRawOutputIdentifier dollar, JSExpression defaultValue)
        {
            var fieldInfo = Translator.TypeInfoProvider.GetField(field);
            var typeKeyword = WasmUtil.PickTypeKeyword(fieldInfo.FieldType);

            // Unhandled type
            if (typeKeyword == null)
                return;

            GetFieldOffset(field);
        }
예제 #19
0
        public void EmitFunctionBody (IAstEmitter astEmitter, MethodDefinition method, JSFunctionExpression function) {
            astEmitter.ReferenceContext.Push();
            astEmitter.ReferenceContext.EnclosingMethod = method;

            try {
                astEmitter.Emit(function);
            } catch (Exception exc) {
                throw new Exception("Error occurred while generating javascript for method '" + method.FullName + "'.", exc);
            } finally {
                astEmitter.ReferenceContext.Pop();
            }

            EmitSemicolon();
            EmitSpacer();
        }
예제 #20
0
        public void EmitFunctionBody(IAstEmitter astEmitter, MethodDefinition method, JSFunctionExpression function)
        {
            // Skip Main() and emit it at the footer
            if (Assembly.EntryPoint == method) {
                // HACK: Store this so we can use it to emit the entry point's body later
                EntryPointAstEmitter = astEmitter;
                return;
            }

            var name = WasmUtil.FormatMemberName(method);

            Switch(PrecedingType.Function, true);

            Formatter.WriteRaw("(func ${0}", name);
            Formatter.Indent();
            Formatter.NewLine();

            int v = 0;
            foreach (var kvp in function.AllVariables) {
                var variable = kvp.Value;

                var type = WasmUtil.PickTypeKeyword(variable.IdentifierType);
                if (type != null) {
                    Formatter.WriteRaw(
                        "({0} ${1} {2}) ",
                        variable.IsParameter
                            ? "param"
                            : "local",
                        WasmUtil.EscapeIdentifier(kvp.Key), type
                    );

                    if (v++ >= 3) {
                        v = 0;
                        Formatter.NewLine();
                    }
                }
            }

            if (function.LabelGroupCount > 0) {
                Formatter.NewLine();
            }
            for (var i = 0; i < function.LabelGroupCount; i++) {
                Formatter.WriteRaw("(local $currentLabel_{0} i32) ", i);
            }

            var returnType = WasmUtil.PickTypeKeyword(method.ReturnType);
            if (returnType != "void") {
                Formatter.NewLine();
                Formatter.WriteRaw("(result {0})", returnType);
            }

            Formatter.ConditionalNewLine();
            Formatter.NewLine();

            astEmitter.Emit(function.Body);

            Formatter.ConditionalNewLine();
            Formatter.Unindent();
            Formatter.WriteRaw(")");

            Formatter.NewLine();
        }
예제 #21
0
        public void EmitMethodDefinition (
            DecompilerContext context, MethodReference methodRef, MethodDefinition method,
            IAstEmitter astEmitter, bool stubbed,
            JSRawOutputIdentifier dollar, MethodInfo methodInfo = null
        ) {
            if (methodInfo == null)
                methodInfo = TypeInfo.GetMemberInformation<Internal.MethodInfo>(method);

            bool isExternal, isReplaced, methodIsProxied;

            if (!Translator.ShouldTranslateMethodBody(
                method, methodInfo, stubbed,
                out isExternal, out isReplaced, out methodIsProxied
            ))
                return;

            JSFunctionExpression function = Translator.GetFunctionBodyForMethod(
                isExternal, methodInfo
            );

            astEmitter.ReferenceContext.EnclosingType = method.DeclaringType;
            astEmitter.ReferenceContext.EnclosingMethod = null;

            Formatter.NewLine();

            astEmitter.ReferenceContext.Push();
            astEmitter.ReferenceContext.DefiningMethod = methodRef;

            try {
                dollar.WriteTo(Formatter);
                Formatter.Dot();
                if (methodInfo.IsPInvoke)
                    // FIXME: Write out dll name from DllImport
                    // FIXME: Write out alternate method name if provided
                    Formatter.Identifier("PInvokeMethod", EscapingMode.None);
                else if (isExternal && !Configuration.GenerateSkeletonsForStubbedAssemblies.GetValueOrDefault(false))
                    Formatter.Identifier("ExternalMethod", EscapingMode.None);
                else
                    Formatter.Identifier("Method", EscapingMode.None);
                Formatter.LPar();

                // FIXME: Include IsVirtual?
                Formatter.MemberDescriptor(method.IsPublic, method.IsStatic, method.IsVirtual, false);

                Formatter.Comma();
                Formatter.Value(Util.EscapeIdentifier(methodInfo.GetName(true), EscapingMode.String));

                Formatter.Comma();
                Formatter.NewLine();

                Formatter.MethodSignature(methodRef, methodInfo.Signature, astEmitter.ReferenceContext);

                if (methodInfo.IsPInvoke && method.HasPInvokeInfo) {
                    Formatter.Comma();
                    Formatter.NewLine();
                    EmitPInvokeInfo(
                        methodRef, method, astEmitter
                    );
                } else if (!isExternal) {
                    Formatter.Comma();
                    Formatter.NewLine();

                    if (function != null) {
                        Formatter.WriteRaw(Util.EscapeIdentifier(function.DisplayName));
                    } else {
                        Formatter.Identifier("JSIL.UntranslatableFunction", EscapingMode.None);
                        Formatter.LPar();
                        Formatter.Value(method.FullName);
                        Formatter.RPar();
                    }
                }

                Formatter.NewLine();
                Formatter.RPar();

                astEmitter.ReferenceContext.AttributesMethod = methodRef;

                EmitOverrides(context, methodInfo.DeclaringType, method, methodInfo, astEmitter);

                EmitCustomAttributes(context, method.DeclaringType, method, astEmitter);

                EmitParameterAttributes(context, method.DeclaringType, method, astEmitter);

                Formatter.Semicolon();
            } finally {
                astEmitter.ReferenceContext.Pop();
            }
        }
예제 #22
0
 public void EmitInterfaceList(TypeInfo typeInfo, IAstEmitter astEmitter, JSRawOutputIdentifier dollar)
 {
 }
예제 #23
0
        protected void EmitEnum (DecompilerContext context, TypeDefinition enm, IAstEmitter astEmitter) {
            var typeInformation = TypeInfo.GetTypeInformation(enm);

            if (typeInformation == null)
                throw new InvalidDataException(String.Format(
                    "No type information for enum '{0}'!",
                    enm.FullName
                ));

            Formatter.Identifier("JSIL.MakeEnum", EscapingMode.None);
            Formatter.LPar();
            Formatter.NewLine();

            Formatter.OpenBrace();

            Formatter.WriteRaw("FullName: ");
            Formatter.Value(Util.DemangleCecilTypeName(typeInformation.FullName));
            Formatter.Comma();
            Formatter.NewLine();

            Formatter.WriteRaw("BaseType: ");
            // FIXME: Will this work on Mono?
            Formatter.TypeReference(enm.Fields.First(f => f.Name == "value__").FieldType, astEmitter.ReferenceContext);
            Formatter.Comma();
            Formatter.NewLine();

            Formatter.WriteRaw("IsPublic: ");
            Formatter.Value(enm.IsPublic);
            Formatter.Comma();
            Formatter.NewLine();

            Formatter.WriteRaw("IsFlags: ");
            Formatter.Value(typeInformation.IsFlagsEnum);
            Formatter.Comma();
            Formatter.NewLine();

            Formatter.CloseBrace(false);
            Formatter.Comma();
            Formatter.NewLine();

            Formatter.OpenBrace();

            foreach (var em in typeInformation.EnumMembers.Values.OrderBy((em) => em.Value)) {
                Formatter.Identifier(em.Name);
                Formatter.WriteRaw(": ");
                Formatter.Value(em.Value);
                Formatter.Comma();
                Formatter.NewLine();
            }

            Formatter.CloseBrace();

            Formatter.RPar();
            Formatter.Semicolon();
            Formatter.NewLine();
        }
예제 #24
0
        public void EmitMethodDefinition(DecompilerContext context, MethodReference methodRef, MethodDefinition method, IAstEmitter astEmitter, bool stubbed, JSRawOutputIdentifier dollar, MethodInfo methodInfo = null)
        {
            // Skip Main() and emit it at the footer
            if (Assembly.EntryPoint == method) {
                // HACK: Store this so we can use it to emit the entry point's body later
                EntryPointAstEmitter = astEmitter;
                return;
            }

            var name = WasmUtil.FormatMemberName(method);

            var sExport = "Wasm.Module.ExportAttribute";

            methodInfo = methodInfo ?? Translator.TypeInfoProvider.GetMethod(methodRef);

            if (methodInfo != null && methodInfo.Metadata.HasAttribute(sExport)) {
                var exportName = method.Name;
                var ap = methodInfo.Metadata.GetAttributeParameters(sExport);
                if ((ap.Count == 1) && (ap[0].Value is string))
                    exportName = (string)ap[0].Value;

                Switch(PrecedingType.Export);

                Formatter.WriteRaw("(export \"{0}\" ${1})", exportName, name);
                Formatter.ConditionalNewLine();
            }
        }
예제 #25
0
        public void EmitEvent (
            DecompilerContext context, IAstEmitter astEmitter, 
            EventDefinition @event, JSRawOutputIdentifier dollar
        ) {
            if (Translator.ShouldSkipMember(@event))
                return;

            var eventInfo = TypeInfo.GetMemberInformation<Internal.EventInfo>(@event);
            if ((eventInfo == null) || eventInfo.IsIgnored)
                return;

            var isStatic = (@event.AddMethod ?? @event.RemoveMethod).IsStatic;

            Formatter.NewLine();

            dollar.WriteTo(Formatter);
            Formatter.Dot();

            if (eventInfo.IsExternal)
                Formatter.Identifier("ExternalEvent", EscapingMode.None);
            else if (@event.DeclaringType.HasGenericParameters && isStatic)
                Formatter.Identifier("GenericEvent", EscapingMode.None);
            else
                Formatter.Identifier("Event", EscapingMode.None);

            Formatter.LPar();

            Formatter.MemberDescriptor(eventInfo.IsPublic, eventInfo.IsStatic, eventInfo.IsVirtual);

            Formatter.Comma();

            Formatter.Value(Util.EscapeIdentifier(eventInfo.Name, EscapingMode.String));

            Formatter.Comma();
            Formatter.TypeReference(@event.EventType, astEmitter.ReferenceContext);

            Formatter.RPar();

            EmitCustomAttributes(context, @event.DeclaringType, @event, astEmitter);

            Formatter.Semicolon();
        }
예제 #26
0
 public void EmitProperty(DecompilerContext context, IAstEmitter astEmitter, PropertyDefinition property, JSRawOutputIdentifier dollar)
 {
 }
예제 #27
0
 public void EmitConstant(DecompilerContext context, IAstEmitter astEmitter, FieldDefinition field, JSRawOutputIdentifier dollar, JSExpression value)
 {
 }
예제 #28
0
 public bool EmitTypeDeclarationHeader(DecompilerContext context, IAstEmitter astEmitter, TypeDefinition typedef, TypeInfo typeInfo)
 {
     return true;
 }
예제 #29
0
 public void EndEmitTypeDefinition(IAstEmitter astEmitter, DecompilerContext context, TypeDefinition typedef)
 {
 }
예제 #30
0
 public void EndEmitTypeDefinition(IAstEmitter astEmitter, DecompilerContext context, TypeDefinition typedef)
 {
 }
예제 #31
0
        public void EmitFunctionBody(IAstEmitter astEmitter, MethodDefinition method, JSFunctionExpression function)
        {
            // Skip Main() and emit it at the footer
            if (Assembly.EntryPoint == method)
            {
                // HACK: Store this so we can use it to emit the entry point's body later
                EntryPointAstEmitter = astEmitter;
                return;
            }

            var name = WasmUtil.FormatMemberName(method);

            Switch(PrecedingType.Function, true);

            Formatter.WriteRaw("(func ${0}", name);
            Formatter.Indent();
            Formatter.NewLine();

            int v = 0;

            foreach (var kvp in function.AllVariables)
            {
                var variable = kvp.Value;

                var type = WasmUtil.PickTypeKeyword(variable.IdentifierType);
                if (type != null)
                {
                    Formatter.WriteRaw(
                        "({0} ${1} {2}) ",
                        variable.IsParameter
                            ? "param"
                            : "local",
                        WasmUtil.EscapeIdentifier(kvp.Key), type
                        );

                    if (v++ >= 3)
                    {
                        v = 0;
                        Formatter.NewLine();
                    }
                }
            }

            if (function.LabelGroupCount > 0)
            {
                Formatter.NewLine();
            }
            for (var i = 0; i < function.LabelGroupCount; i++)
            {
                Formatter.WriteRaw("(local $currentLabel_{0} i32) ", i);
            }

            var returnType = WasmUtil.PickTypeKeyword(method.ReturnType);

            if (returnType != "void")
            {
                Formatter.NewLine();
                Formatter.WriteRaw("(result {0})", returnType);
            }

            Formatter.ConditionalNewLine();
            Formatter.NewLine();

            astEmitter.Emit(function.Body);

            Formatter.ConditionalNewLine();
            Formatter.Unindent();
            Formatter.WriteRaw(")");

            Formatter.NewLine();
        }
예제 #32
0
 public void BeginEmitTypeDefinition(IAstEmitter astEmitter, TypeDefinition typedef, TypeInfo typeInfo, TypeReference baseClass)
 {
     TypesToStaticInitialize.Add(typedef);
 }
예제 #33
0
        public void EndEmitTypeDefinition (IAstEmitter astEmitter, DecompilerContext context, TypeDefinition typedef) {
            Formatter.NewLine();
            Formatter.NewLine();
            Formatter.WriteRaw("return function (newThisType) { $thisType = newThisType; }");
            Formatter.Semicolon(false);

            Formatter.NewLine();

            Formatter.CloseBrace(false);

            // Hack to force the indent level for type definitions to be 1 instead of 2.
            Formatter.Indent();

            Formatter.RPar();

            EmitCustomAttributes(context, typedef.DeclaringType, typedef, astEmitter);

            Formatter.Semicolon();
            Formatter.NewLine();

            astEmitter.ReferenceContext.Pop();

            Formatter.Unindent();
            Formatter.WriteRaw("})();");
            Formatter.NewLine();
            Formatter.NewLine();
        }
예제 #34
0
 public void EmitCachedValues(IAstEmitter astEmitter, TypeExpressionCacher typeCacher, SignatureCacher signatureCacher, BaseMethodCacher baseMethodCacher)
 {
 }
예제 #35
0
        private void EmitFieldOrConstant (
            DecompilerContext context, IAstEmitter astEmitter, 
            FieldDefinition field, JSRawOutputIdentifier dollar, 
            JSExpression defaultValue, bool isConstant
        ) {
            var fieldInfo = TypeInfo.GetMemberInformation<Internal.FieldInfo>(field);
            if ((fieldInfo == null) || fieldInfo.IsIgnored)
                return;

            Formatter.NewLine();

            dollar.WriteTo(Formatter);
            Formatter.Dot();
            Formatter.Identifier(
                isConstant 
                    ? "Constant"
                    : "Field", EscapingMode.None
            );
            Formatter.LPar();

            Formatter.MemberDescriptor(
                field.IsPublic, fieldInfo.IsStatic,
                isReadonly: field.IsInitOnly,
                offset: field.DeclaringType.IsExplicitLayout 
                    ? (int?)field.Offset 
                    : null
            );

            Formatter.Comma();

            var fieldName = Util.EscapeIdentifier(fieldInfo.Name, EscapingMode.MemberIdentifier);

            Formatter.Value(fieldName);

            Formatter.Comma();

            Formatter.TypeReference(fieldInfo.FieldType, astEmitter.ReferenceContext);

            if (defaultValue != null) {
                Formatter.Comma();
                astEmitter.Emit(defaultValue);
            }

            Formatter.RPar();

            EmitCustomAttributes(context, field.DeclaringType, field, astEmitter);

            Formatter.Semicolon();
        }
 public virtual void EmitField(DecompilerContext context, IAstEmitter astEmitter, FieldDefinition field, JSRawOutputIdentifier dollar, JSExpression defaultValue)
 {
 }
예제 #37
0
        public void EmitInterfaceDefinition (
            DecompilerContext context, IAstEmitter astEmitter, TypeDefinition iface
        ) {
            var typeInfo = TypeInfo.GetTypeInformation(iface);

            Formatter.Identifier("JSIL.MakeInterface", EscapingMode.None);
            Formatter.LPar();
            Formatter.NewLine();
            
            Formatter.Value(Util.DemangleCecilTypeName(typeInfo.FullName));
            Formatter.Comma();

            Formatter.Value(iface.IsPublic);
            Formatter.Comma();

            Formatter.OpenBracket();
            WriteGenericParameterNames(iface.GenericParameters);
            Formatter.CloseBracket();

            Formatter.Comma();
            Formatter.OpenFunction(null, (f) =>
                f.Identifier("$")
            );

            var refContext = new TypeReferenceContext {
                EnclosingType = iface,
                DefiningType = iface
            };

            bool isFirst = true;
            foreach (var methodGroup in iface.Methods.GroupBy(md => md.Name)) {
                foreach (var m in methodGroup) {
                    if (Translator.ShouldSkipMember(m))
                        continue;

                    var methodInfo = TypeInfo.GetMethod(m);

                    if ((methodInfo == null) || methodInfo.IsIgnored)
                        continue;

                    Formatter.Identifier("$", EscapingMode.None);
                    Formatter.Dot();
                    Formatter.Identifier("Method", EscapingMode.None);
                    Formatter.LPar();

                    var renamedName = methodInfo.Name;
                    var offset = renamedName.IndexOf("`");
                    if (offset > 0)
                        renamedName = renamedName.Substring(0, offset);

                    if (renamedName != m.Name) {
                        Formatter.WriteRaw("{OriginalName: ");
                        Formatter.Value(m.Name);
                        Formatter.WriteRaw("}");
                    } else {
                        Formatter.WriteRaw("{}");
                    }
                    Formatter.Comma();

                    Formatter.Value(Util.EscapeIdentifier(renamedName, EscapingMode.String));
                    Formatter.Comma();

                    Formatter.MethodSignature(m, methodInfo.Signature, refContext);

                    Formatter.RPar();
                    Formatter.Semicolon(true);
                }
            }

            foreach (var p in iface.Properties) {
                if (Translator.ShouldSkipMember(p))
                    continue;

                var propertyInfo = TypeInfo.GetProperty(p);
                if ((propertyInfo != null) && propertyInfo.IsIgnored)
                    continue;

                Formatter.Identifier("$", EscapingMode.None);
                Formatter.Dot();
                Formatter.Identifier("Property", EscapingMode.None);
                Formatter.LPar();

                Formatter.WriteRaw("{}");
                Formatter.Comma();

                Formatter.Value(Util.EscapeIdentifier(p.Name, EscapingMode.String));

                Formatter.RPar();
                Formatter.Semicolon(true);
            }

            Formatter.CloseBrace(false);

            Formatter.Comma();

            refContext = new TypeReferenceContext {
                EnclosingType = iface.DeclaringType,
                DefiningType = iface
            };

            Formatter.OpenBracket();
            foreach (var i in iface.Interfaces) {
                if (Translator.ShouldSkipMember(i))
                {
                    continue;
                }
                if (!isFirst) {
                    Formatter.Comma();
                }

                Formatter.TypeReference(i, refContext);

                isFirst = false;
            }
            Formatter.CloseBracket();

            Formatter.RPar();

            EmitCustomAttributes(context, iface, iface, astEmitter);

            Formatter.Semicolon();
            Formatter.NewLine();
        }
예제 #38
0
 public void BeginEmitTypeDefinition(IAstEmitter astEmitter, TypeDefinition typedef, TypeInfo typeInfo, TypeReference baseClass)
 {
 }
예제 #39
0
 public void EmitConstant (DecompilerContext context, IAstEmitter astEmitter, FieldDefinition field, JSRawOutputIdentifier dollar, JSExpression value) {
     EmitFieldOrConstant(context, astEmitter, field, dollar, value, true);
 }
예제 #40
0
 public void EmitCustomAttributes(DecompilerContext context, TypeReference declaringType, ICustomAttributeProvider member, IAstEmitter astEmitter, bool standalone = true)
 {
 }
예제 #41
0
        private void EmitParameterAttributes (
            DecompilerContext context,
            TypeReference declaringType,
            MethodDefinition method,
            IAstEmitter astEmitter
        ) {
            Formatter.Indent();

            foreach (var parameter in method.Parameters) {
                if (!parameter.HasCustomAttributes && !Configuration.CodeGenerator.EmitAllParameterNames.GetValueOrDefault(false))
                    continue;

                Formatter.NewLine();
                Formatter.Dot();
                Formatter.Identifier("Parameter");
                Formatter.LPar();

                Formatter.Value(parameter.Index);
                Formatter.Comma();

                Formatter.Value(parameter.Name);
                Formatter.Comma();

                Formatter.OpenFunction(null, (jf) => jf.Identifier("_"));

                Formatter.Identifier("_");

                EmitCustomAttributes(context, declaringType, parameter, astEmitter, false);

                Formatter.NewLine();

                Formatter.CloseBrace(false);

                Formatter.RPar();
            }

            Formatter.Unindent();
        }
예제 #42
0
 public void EmitEvent(DecompilerContext context, IAstEmitter astEmitter, EventDefinition @event, JSRawOutputIdentifier dollar)
 {
 }
예제 #43
0
        protected void EmitOverrides (
            DecompilerContext context, TypeInfo typeInfo,
            MethodDefinition method, MethodInfo methodInfo,
            IAstEmitter astEmitter
        ) {
            astEmitter.ReferenceContext.Push();
            try {
                astEmitter.ReferenceContext.EnclosingType = null;
                astEmitter.ReferenceContext.DefiningType = null;

                Formatter.Indent();

                foreach (var @override in methodInfo.Overrides) {
                    Formatter.NewLine();
                    Formatter.Dot();
                    Formatter.Identifier("Overrides");
                    Formatter.LPar();

                    Formatter.TypeReference(@override.InterfaceType, astEmitter.ReferenceContext);

                    Formatter.Comma();
                    Formatter.Value(@override.MemberIdentifier.Name);

                    Formatter.RPar();
                }

                Formatter.Unindent();
            } finally {
                astEmitter.ReferenceContext.Pop();
            }
        }
예제 #44
0
 public void EmitFunctionBody(IAstEmitter astEmitter, MethodDefinition method, JSFunctionExpression function)
 {
 }
예제 #45
0
        private void EmitMarshalInfo (
            MethodReference methodRef, MethodDefinition method,
            Mono.Cecil.ParameterAttributes attributes, MarshalInfo mi, 
            IAstEmitter astEmitter
        ) {
            Formatter.OpenBrace();

            if (mi.NativeType == NativeType.CustomMarshaler) {
                var cmi = (CustomMarshalInfo)mi;

                Formatter.WriteRaw("CustomMarshaler: ");
                Formatter.TypeReference(cmi.ManagedType, astEmitter.ReferenceContext);

                if (cmi.Cookie != null) {
                    Formatter.Comma();
                    Formatter.WriteRaw("Cookie: ");
                    Formatter.Value(cmi.Cookie);
                }
            } else {
                Formatter.WriteRaw("NativeType: ");
                Formatter.Value(mi.NativeType.ToString());
            }

            if (attributes.HasFlag(Mono.Cecil.ParameterAttributes.Out)) {
                Formatter.Comma();
                Formatter.NewLine();
                Formatter.WriteRaw("Out: true");
                Formatter.NewLine();
            } else {
                Formatter.NewLine();
            }

            Formatter.CloseBrace(false);
        }
예제 #46
0
 public void EmitMethodDefinition(DecompilerContext context, MethodReference methodRef, MethodDefinition method, IAstEmitter astEmitter, bool stubbed, JSRawOutputIdentifier dollar, MethodInfo methodInfo = null)
 {
 }
예제 #47
0
        protected void EmitDelegate (DecompilerContext context, TypeDefinition del, TypeInfo typeInfo, IAstEmitter astEmitter) {
            Formatter.Identifier("JSIL.MakeDelegate", EscapingMode.None);
            Formatter.LPar();

            Formatter.Value(Util.DemangleCecilTypeName(del.FullName));
            Formatter.Comma();

            Formatter.Value(del.IsPublic);

            Formatter.Comma();
            Formatter.OpenBracket();
            if (del.HasGenericParameters)
                WriteGenericParameterNames(del.GenericParameters);
            Formatter.CloseBracket();

            var invokeMethod = del.Methods.FirstOrDefault(method => method.Name == "Invoke");
            if (invokeMethod != null)
            {
                Formatter.Comma();
                Formatter.NewLine();

                astEmitter.ReferenceContext.Push();
                astEmitter.ReferenceContext.DefiningType = del;
                try
                {
                    Formatter.MethodSignature(invokeMethod,
                                           typeInfo.MethodSignatures.GetOrCreateFor("Invoke").First(),
                                           astEmitter.ReferenceContext);

                }
                finally
                {
                    astEmitter.ReferenceContext.Pop();
                }

                if (
                    invokeMethod.HasPInvokeInfo || 
                    invokeMethod.MethodReturnType.HasMarshalInfo ||
                    invokeMethod.Parameters.Any(p => p.HasMarshalInfo)
                ) {
                    Formatter.Comma();
                    EmitPInvokeInfo(invokeMethod, invokeMethod, astEmitter);
                    Formatter.NewLine();
                }
            }

            Formatter.RPar();
            Formatter.Semicolon();
            Formatter.NewLine();
        }
예제 #48
0
 public void EmitInterfaceList(TypeInfo typeInfo, IAstEmitter astEmitter, JSRawOutputIdentifier dollar)
 {
 }
예제 #49
0
        public void EmitProperty (
            DecompilerContext context, IAstEmitter astEmitter,
            PropertyDefinition property, JSRawOutputIdentifier dollar
        ) {
            if (Translator.ShouldSkipMember(property))
                return;

            var propertyInfo = TypeInfo.GetMemberInformation<Internal.PropertyInfo>(property);
            if ((propertyInfo == null) || propertyInfo.IsIgnored)
                return;

            var isStatic = (property.SetMethod ?? property.GetMethod).IsStatic;

            Formatter.NewLine();

            dollar.WriteTo(Formatter);
            Formatter.Dot();

            if (propertyInfo.IsExternal)
                Formatter.Identifier("ExternalProperty", EscapingMode.None);
            else if (property.DeclaringType.HasGenericParameters && isStatic)
                Formatter.Identifier("GenericProperty", EscapingMode.None);
            else
                Formatter.Identifier("Property", EscapingMode.None);

            Formatter.LPar();

            Formatter.MemberDescriptor(propertyInfo.IsPublic, propertyInfo.IsStatic, propertyInfo.IsVirtual);

            Formatter.Comma();

            Formatter.Value(Util.EscapeIdentifier(propertyInfo.Name, EscapingMode.String));

            Formatter.Comma();
            Formatter.TypeReference(property.PropertyType, astEmitter.ReferenceContext);

            Formatter.RPar();

            EmitCustomAttributes(context, property.DeclaringType, property, astEmitter);

            Formatter.Semicolon();
        }
예제 #50
0
        public void EmitMethodDefinition(DecompilerContext context, MethodReference methodRef, MethodDefinition method, IAstEmitter astEmitter, bool stubbed, JSRawOutputIdentifier dollar, MethodInfo methodInfo = null)
        {
            // Skip Main() and emit it at the footer
            if (Assembly.EntryPoint == method)
            {
                // HACK: Store this so we can use it to emit the entry point's body later
                EntryPointAstEmitter = astEmitter;
                return;
            }

            var name = WasmUtil.FormatMemberName(method);

            var sExport = "Wasm.Module.ExportAttribute";

            methodInfo = methodInfo ?? Translator.TypeInfoProvider.GetMethod(methodRef);

            if (methodInfo != null && methodInfo.Metadata.HasAttribute(sExport))
            {
                var exportName = method.Name;
                var ap         = methodInfo.Metadata.GetAttributeParameters(sExport);
                if ((ap.Count == 1) && (ap[0].Value is string))
                {
                    exportName = (string)ap[0].Value;
                }

                Switch(PrecedingType.Export);

                Formatter.WriteRaw("(export \"{0}\" ${1})", exportName, name);
                Formatter.ConditionalNewLine();
            }
        }
예제 #51
0
        public void BeginEmitTypeDefinition (
            IAstEmitter astEmitter, 
            TypeDefinition typedef, TypeInfo typeInfo,
            TypeReference baseClass
        ) {
            Formatter.NewLine();

            bool isStaticClass = typedef.IsAbstract && typedef.IsSealed;

            if (isStaticClass) {
                Formatter.Identifier("JSIL.MakeStaticClass", EscapingMode.None);
                Formatter.LPar();

                Formatter.Value(Util.DemangleCecilTypeName(typeInfo.FullName));
                Formatter.Comma();
                Formatter.Value(typedef.IsPublic);

                Formatter.Comma();
                Formatter.OpenBracket();
                if (typedef.HasGenericParameters)
                    WriteGenericParameterNames(typedef.GenericParameters);
                Formatter.CloseBracket();

            } else {
                Formatter.Identifier("JSIL.MakeType", EscapingMode.None);

                Formatter.LPar();
                Formatter.OpenBrace();

                Formatter.WriteRaw("BaseType: ");

                if (baseClass == null) {
                    if (typedef.FullName != "System.Object") {
                        throw new InvalidDataException(String.Format(
                            "Type '{0}' has no base class and isn't System.Object.",
                            typedef.FullName
                        ));
                    }

                    Formatter.Identifier("$jsilcore");
                    Formatter.Dot();
                    Formatter.Identifier("TypeRef");
                    Formatter.LPar();
                    Formatter.Value("System.Object");
                    Formatter.RPar();
                } else if (typedef.FullName == "System.ValueType") {
                    Formatter.Identifier("$jsilcore");
                    Formatter.Dot();
                    Formatter.Identifier("TypeRef");
                    Formatter.LPar();
                    Formatter.Value("System.ValueType");
                    Formatter.RPar();
                } else {
                    Formatter.TypeReference(baseClass, astEmitter.ReferenceContext);
                }

                Formatter.Comma();
                Formatter.NewLine();

                Formatter.WriteRaw("Name: ");
                Formatter.Value(Util.DemangleCecilTypeName(typeInfo.FullName));
                Formatter.Comma();
                Formatter.NewLine();

                Formatter.WriteRaw("IsPublic: ");
                Formatter.Value(typedef.IsPublic);
                Formatter.Comma();
                Formatter.NewLine();

                Formatter.WriteRaw("IsReferenceType: ");
                Formatter.Value(!typedef.IsValueType);
                Formatter.Comma();
                Formatter.NewLine();

                if (typedef.HasGenericParameters) {
                    Formatter.WriteRaw("GenericParameters: ");
                    Formatter.OpenBracket();
                    WriteGenericParameterNames(typedef.GenericParameters);
                    Formatter.CloseBracket();
                    Formatter.Comma();
                    Formatter.NewLine();
                }

                var constructors = typedef.Methods.Where((m) => m.IsConstructor).ToList();
                if ((constructors.Count != 0) || typedef.IsValueType) {
                    Formatter.WriteRaw("MaximumConstructorArguments: ");

                    if (typedef.IsValueType && (constructors.Count == 0))
                        Formatter.Value(0);
                    else
                        Formatter.Value(constructors.Max((m) => m.Parameters.Count));

                    Formatter.Comma();
                    Formatter.NewLine();
                }

                if (typedef.IsExplicitLayout) {
                    Formatter.WriteRaw("ExplicitLayout: true");
                    Formatter.Comma();
                    Formatter.NewLine();
                } else if (typedef.IsSequentialLayout) {
                    Formatter.WriteRaw("SequentialLayout: true");
                    Formatter.Comma();
                    Formatter.NewLine();
                }

                if (typedef.HasLayoutInfo) {
                    if (typedef.PackingSize != 0) {
                        Formatter.WriteRaw("Pack: ");
                        Formatter.Value(typedef.PackingSize);
                        Formatter.Comma();
                        Formatter.NewLine();
                    }

                    if (typedef.ClassSize != 0) {
                        Formatter.WriteRaw("SizeBytes: ");
                        Formatter.Value(typedef.ClassSize);
                        Formatter.Comma();
                        Formatter.NewLine();
                    }
                }

                Formatter.CloseBrace(false);
            }

            // Hack to force the indent level for type definitions to be 1 instead of 2.
            Formatter.Unindent();

            Formatter.Comma();
            Formatter.OpenFunction(null, (f) => 
                f.Identifier("$ib")
            );

            Formatter.WriteRaw("$ = $ib;");
            Formatter.NewLine();

            astEmitter.ReferenceContext.Push();
            astEmitter.ReferenceContext.EnclosingType = typedef;
        }
예제 #52
0
 public void EmitProperty(DecompilerContext context, IAstEmitter astEmitter, PropertyDefinition property, JSRawOutputIdentifier dollar)
 {
 }