示例#1
0
        private JsExpression VisitLambdaExpression(ExpressionSyntax node, ParameterSyntax[] parameters, CSharpSyntaxNode body)
        {
            var expressionType = (INamedTypeSymbol)model.GetTypeInfo(node).ConvertedType;
            INamedTypeSymbol delegateType;

            if (Equals(expressionType.OriginalDefinition, Context.Instance.ExpressionGeneric))
            {
                delegateType = (INamedTypeSymbol)expressionType.TypeArguments[0];
            }
            else
            {
                delegateType = expressionType;
            }
            var lambdaParameters = parameters.ToArray();
            var delegateMethod   = (IMethodSymbol)delegateType.GetMembers("Invoke")[0];
//            Compiler.CsCompilation.FindType()
            var lambdaMethods   = Context.Instance.Expression.GetMembers("Lambda").OfType <IMethodSymbol>().ToArray();
            var lambdaMethods2  = lambdaMethods.Where(x => x.TypeParameters.Count() == 1 && x.Parameters.Count() == 2 && Equals(x.Parameters[0].Type, Context.Instance.Expression) && Equals(x.Parameters[1].Type, Context.Instance.ParameterExpressionArray)).ToArray();
            var lambdaMethod    = lambdaMethods2.Single();
            var parameterMethod = Context.Instance.Expression.GetMembers("Parameter").OfType <IMethodSymbol>().Single(x => x.Parameters.Count() == 2 && Equals(x.Parameters[0].Type, Context.Instance.TypeType) && Equals(x.Parameters[1].Type, Context.Instance.String));

            lambdaMethod = lambdaMethod.Construct(delegateType);

            var jsLambda = idioms.InvokeStatic(lambdaMethod);

            // Convert parameters
            var workspace    = new JsBlockStatement();
            var jsParameters = Js.Array();

            for (var i = 0; i < delegateMethod.Parameters.Count(); i++)
            {
                var delegateParameter     = delegateMethod.Parameters[i];
                var lambdaParameter       = lambdaParameters[i];
                var jsParameter           = idioms.InvokeStatic(parameterMethod, idioms.TypeOf(delegateParameter.Type), Js.Primitive(lambdaParameter.Identifier.ToString()));
                var parameterVariableName = "$lambdaparam$" + lambdaParameter.Identifier;
                parameterVariables[lambdaParameter.Identifier.ToString()] = parameterVariableName;

                // Declare a variable to hold the parameter object in the parenthetical's scope
                workspace.Local(parameterVariableName, jsParameter);

                // Add a reference to this variable (a ParameterExpression) as one of the
                // parameters to the lambda.
                jsParameters.Elements.Add(Js.Reference(parameterVariableName));
            }

            var jsBody = body.Accept(this);

            jsLambda.AddArgument(jsBody);
            jsLambda.AddArgument(jsParameters);
            workspace.Return(jsLambda);

            return(idioms.Wrap(workspace));
        }
示例#2
0
        public async Task Compile()
        {
            projectName = project.AssemblyName;
            Compilation compilation = await Profiler.Time("Getting initial project compilation", async() => await project.GetCompilationAsync());

            Context.Update(project.Solution, project, compilation, new ReflectionCache(project, compilation));

            // If this is the runtime prjoect, declare the array to hold all the GetAssembly functions (this .js file
            // will be loaded first, and we only want to bother creating the array once.)
            if (projectName == "mscorlib")
            {
                var global = new JsBlockStatement();
                jsCompilationUnit.Global = global;

                var assemblies = Js.Variable(SpecialNames.Assemblies, Js.Array());
                global.Local(assemblies);

                // This ensures that Function.$typeName returns `Function` -- this is important when using
                // a type function as a generic argument, since otherwise when we try to get a
                // unique key for the permuatation of type args including a type function, we would get
                // an empty string for that arg, which would break the cache.
                jsCompilationUnit.Body.Assign(Js.Reference("Function").Member(SpecialNames.TypeName), Js.Primitive("Function"));
            }

            // Declare assembly variable
            var assemblyVariable = Js.Variable("$" + projectName.MaskSpecialCharacters() + "$Assembly", Js.Null());

            jsCompilationUnit.Body.Local(assemblyVariable);

            // Declare array to store all anonymous types
            var anonymousTypes = Js.Variable(compilation.Assembly.GetAssemblyAnonymousTypesArray(), Js.Array());

            jsCompilationUnit.Body.Local(anonymousTypes);

            // Declare array to store all the type functions in the assembly
            var assemblyTypes = Js.Variable(compilation.Assembly.GetAssemblyTypesArray(), Js.Array());

            jsCompilationUnit.Body.Local(assemblyTypes);

            // Build $GetAssemblyMethod, which lazily creates a new Assembly instance
            var globalIdioms = new Idioms(null);
            var getAssembly  = Js.Function();

            getAssembly.Body.If(
                assemblyVariable.GetReference().EqualTo(Js.Null()),
                assemblyVariable.GetReference().Assign(globalIdioms.CreateAssembly(compilation.Assembly, assemblyTypes.GetReference()))
                );
            getAssembly.Body.Return(assemblyVariable.GetReference());
            jsCompilationUnit.Body.Assign(
                Js.Reference(compilation.Assembly.GetAssemblyMethodName()),
                getAssembly);

            // Declare $assembly variable
            jsCompilationUnit.Body.Local(SpecialNames.Assembly, Js.Reference(compilation.Assembly.GetAssemblyMethodName()));
            jsCompilationUnit.Body.Assign(Js.Reference(SpecialNames.Assembly).Member(SpecialNames.AssemblyTypesArray), assemblyTypes.GetReference());

            // Add $GetAssemblyMethod to global assemblies array
            jsCompilationUnit.Body.Express(Js.Reference(SpecialNames.Assemblies).Member("push").Invoke(Js.Reference(SpecialNames.Assembly)));

            // Builds out all the namespace objects.  Types live inside namepsaces, which are represented as
            // nested Javascript objects.  For example, System.Text.StringBuilder is represented (in part) as:
            //
            // System = {};
            // System.Text = {};
            // System.Text.StringBuilder = function() { ... }
            //
            // This allows access to classes using dot notation in the expected way.
            Profiler.Time("Transforming namespaces", () =>
            {
                var namespaceTransformer = new NamespaceTransformer(jsCompilationUnit.Body);
                foreach (var syntaxTree in compilation.SyntaxTrees)
                {
                    var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot();
                    compilationUnit.Accept(namespaceTransformer);
                }
            });

            var actions = new List <Tuple <INamedTypeSymbol, Action> >();

            Profiler.Time("Get diagnostics", () =>
            {
                var diagnostics = compilation.GetDiagnostics();
                foreach (var diagnostic in diagnostics)
                {
                    if (diagnostic.Severity == DiagnosticSeverity.Error)
                    {
                        Console.WriteLine("// " + diagnostic);
                    }
                }
            });

            // Check for partial classes
            Profiler.Time("Reassemble partial classes", () =>
            {
                var partialClassReassembler = new PartialClassReassembler(project, compilation);
                compilation = partialClassReassembler.UnifyPartialTypes();
            });

/*
 *          // Write out all type functions in inheritance order.  This allows for complex references between types and
 *          // nested types.
 *          Profiler.Time("Write out type function declarations", () =>
 *          {
 *              var allTypeDeclarations = new List<INamedTypeSymbol>();
 *              foreach (var syntaxTree in compilation.SyntaxTrees)
 *              {
 *                  var semanticModel = compilation.GetSemanticModel(syntaxTree);
 *                  var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot();
 *                  var typeDeclarations = GetTypeDeclarations(compilationUnit);
 *                  var types = typeDeclarations.Select(x => semanticModel.GetDeclaredSymbol(x)).ToArray();
 *                  allTypeDeclarations.AddRange(types);
 *              }
 *              SweepSort(allTypeDeclarations, x => x);
 *
 *              jsCompilationUnit.Body.Express(Js.Reference(Context.Instance.SymbolNames[classType.ContainingNamespace, classType.ContainingNamespace.GetFullName()]).Member(classType.GetShortTypeName()),
 *                      Js.Reference(SpecialNames.Define).Invoke(Js.Primitive(displayName), baseType));
 *              jsCompilationUnit.Assign(Js.Reference(Context.Instance.SymbolNames[classType.ContainingNamespace, classType.ContainingNamespace.GetFullName()]).Member(classType.GetShortTypeName()),
 *                      Js.Reference(SpecialNames.Define).Invoke(Js.Primitive(displayName), baseType));
 *          });
 */

            // Scan all syntax trees for anonymous type creation expressions.  We transform them into class
            // declarations with a series of auto implemented properties.
            Profiler.Time("Running AnonymousTypeTransformer", () =>
            {
                var anonymousTypeTransformer = new AnonymousTypeTransformer(jsCompilationUnit.Body, actions);
                foreach (var syntaxTree in compilation.SyntaxTrees)
                {
                    var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot();
                    compilationUnit.Accept(anonymousTypeTransformer);
                }
            });

            // Iterate through all the syntax trees and add entries into `actions` that correspond to type
            // declarations.
            Profiler.Time("Preparing for core transformation process", () =>
            {
                foreach (var syntaxTree in compilation.SyntaxTrees)
                {
                    var semanticModel   = compilation.GetSemanticModel(syntaxTree);
                    var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot();
                    var transformer     = new JsTransformer(syntaxTree, semanticModel, jsCompilationUnit);

                    var typeCollector = new TypeCollector();
                    compilationUnit.Accept(typeCollector);
                    var typeDeclarations     = typeCollector.TypeDeclarations.Where(x => x.GetContainingTypeDeclaration() == null);
                    var delegateDeclarations = typeCollector.DelegateDeclarations.Where(x => x.GetContainingTypeDeclaration() == null);

                    foreach (var type in typeDeclarations)
                    {
                        var _type      = type;
                        var typeSymbol = semanticModel.GetDeclaredSymbol(type);
                        Action action  = () =>
                        {
                            var statements = (JsBlockStatement)_type.Accept(transformer);
                            jsCompilationUnit.Body.Aggregate(statements);
                        };
                        actions.Add(Tuple.Create(typeSymbol, action));
                    }
                    foreach (var type in delegateDeclarations)
                    {
                        var _type     = type;
                        Action action = () =>
                        {
                            var statements = (JsBlockStatement)_type.Accept(transformer);
                            jsCompilationUnit.Body.Aggregate(statements);
                        };
                        actions.Add(Tuple.Create((INamedTypeSymbol)ModelExtensions.GetDeclaredSymbol(semanticModel, type), action));
                    }
                }
            });

            // Sort all the type declarations such that base types always come before subtypes.
            Profiler.Time("Sorting transformers", () => SweepSort(actions, x => x.Item1));

            var transformationActions = actions.Select(x => x.Item2).ToArray();

            Profiler.Time("Applying core transformation", () =>
            {
                foreach (var item in transformationActions)
                {
                    item();
                }
            });

            // Create cultures based on installed .NET cultures.  Presumably this is the same regardless
            // of the platform that compiled this assembly.  Only do this for the standard library.
            if (projectName == "mscorlib" && !Context.Instance.Compilation.Assembly.IsCultureInfoExportDisabled())
            {
                foreach (var culture in CultureInfo.GetCultures(CultureTypes.AllCultures))
                {
                    JsExpression target = new JsVariableReferenceExpression(Context.Instance.CultureInfo.GetTypeName()).Invoke().Member("RegisterCulture");
                    jsCompilationUnit.Body.Add(target.Invoke(new[]
                    {
                        Js.Literal(culture.Name),
                        Js.Literal(culture.DateTimeFormat.ShortDatePattern),
                        Js.Literal(culture.DateTimeFormat.LongDatePattern),
                        Js.Literal(culture.DateTimeFormat.ShortTimePattern),
                        Js.Literal(culture.DateTimeFormat.LongTimePattern),
                        Js.Literal(culture.DateTimeFormat.FullDateTimePattern),
                        Js.Literal(culture.DateTimeFormat.YearMonthPattern),
                        Js.Array(culture.DateTimeFormat.MonthNames.Select(x => Js.Literal(x)).ToArray()),
                        Js.Array(culture.DateTimeFormat.AbbreviatedMonthNames.Select(x => Js.Literal(x)).ToArray()),
                        Js.Array(culture.DateTimeFormat.DayNames.Select(x => Js.Literal(x)).ToArray())
                    }).Express());
                }
            }

            // If the project type is a console application, then invoke the Main method at the very
            // end of the file.
            var entryPoint = Context.Instance.Compilation.GetEntryPoint(CancellationToken.None);

            if (entryPoint != null)
            {
                jsCompilationUnit.Body.Express(globalIdioms.InvokeStatic(entryPoint));
            }

            // Test minification
//            var minifier = new JsMinifier();
//            jsCompilationUnit.Accept(minifier);
        }
示例#3
0
        private JsStatement TransformBody(JsStatement body)
        {
            var block = body is JsBlockStatement ? (JsBlockStatement)body : Js.Block(body);

            if (!escapeStatements.Any())
            {
                return(Js.Express(idioms.Wrap(block)));
            }
            else
            {
                if (!(block.Statements.Last() is JsReturnStatement))
                {
                    block.Return(Js.Object(Js.Item(EscapeTypeField, Js.Primitive(0))).Compact());
                }
                var wrapped    = idioms.Wrap(block);
                var outerBlock = new JsBlockStatement();
                var loopResult = outerBlock.Local("$loopResult", wrapped);
                if (escapeStatements.Any(x => x.Type == Return))
                {
                    outerBlock.If(loopResult.GetReference().Member(EscapeTypeField).EqualTo(Js.Primitive(Return)),
                                  Js.Return(loopResult.GetReference().Member(EscapeValueField)));
                }
                if (escapeStatements.Any(x => x.Type == Continue))
                {
                    var         escapes = escapeStatements.Where(x => x.Type == Continue).Distinct();
                    JsStatement ifTrue;
                    if (!escapes.Any(x => x.Label != null))
                    {
                        ifTrue = Js.Continue();
                    }
                    else
                    {
                        ifTrue = Js.Switch(
                            loopResult.GetReference().Member(EscapeLabelField),
                            escapes
                            .Where(x => x.Label == null)
                            .Select(x => Js.Section(Js.Null()).Statement(Js.Continue()))
                            .Concat(escapes
                                    .Where(x => x.Label != null && transformer.GetLabelDepth(x.Label) == loopDepth)
                                    .Select(x => Js.Section(Js.Primitive(x.Label)).Statement(Js.Continue(x.Label))))
                            .Concat(new[] { Js.Section(Js.DefaultLabel()).Statements(Js.Return(loopResult.GetReference())) })
                            .ToArray());
                    }
                    outerBlock.If(loopResult.GetReference().Member(EscapeTypeField).EqualTo(Js.Primitive(Continue)),
                                  ifTrue);
                }
                if (escapeStatements.Any(x => x.Type == Break))
                {
                    var         escapes = escapeStatements.Where(x => x.Type == Break).Distinct();
                    JsStatement ifTrue;
                    if (!escapes.Any(x => x.Label != null))
                    {
                        ifTrue = Js.Break();
                    }
                    else
                    {
                        ifTrue = Js.Switch(loopResult.GetReference().Member(EscapeLabelField),
                                           escapes.Select(x => Js.Section(Js.Primitive(x.Label)).Statement(Js.Break(x.Label))).ToArray());
                    }
                    outerBlock.If(loopResult.GetReference().Member(EscapeTypeField).EqualTo(Js.Primitive(Break)),
                                  ifTrue);
                }
                return(outerBlock);
            }
        }
示例#4
0
文件: Idioms.cs 项目: x335/WootzJs
        private JsExpression CreateAttributes(ISymbol symbol)
        {
            var result = Js.Array();
            foreach (var attribute in symbol.GetAttributes().Where(x => x.AttributeClass.IsExported()))
            {
                if (!attribute.AttributeClass.IsExported())
                    continue;

                var attributeInstance = CreateObject(attribute.AttributeConstructor,
                    attribute.ConstructorArguments.Select(x => GetConstantValue(x.Type, x.Value)).ToArray());
                if (attribute.NamedArguments.Any())
                {
                    // Wrap initialization in an anonymous function
                    var initializerBlock = new JsBlockStatement();
                    var variable = Js.Variable("$obj$", attributeInstance);
                    initializerBlock.Local(variable);

                    // Process named arguments
                    foreach (var argument in attribute.NamedArguments)
                    {
                        initializerBlock.Express(variable.GetReference().Member("set_" + argument.Key).Invoke(Js.Literal(argument.Value)));
                    }

                    // Return obj
                    initializerBlock.Return(Js.Reference("$obj$"));

                    attributeInstance = Wrap(initializerBlock);
                }
                result.Elements.Add(attributeInstance);
            }
            return MakeArray(result, Context.Instance.Compilation.CreateArrayTypeSymbol(Context.Instance.Attribute));
        }
示例#5
0
文件: Idioms.cs 项目: x335/WootzJs
        /// <summary>
        /// This generates the entire state machine as an inline function.  State machine fields are represented
        /// as closed variables of an outer function.  The actual "MoveNext" function is an inner function.
        /// </summary>
        public JsBlockStatement GenerateYieldMethod(CSharpSyntaxNode node, IMethodSymbol method)
        {
            var block = new JsBlockStatement();
            var stateMachineBody = Js.Block();
            var stateMachineFunc = block.Local("$stateMachineFunc", Js.Function().Body(stateMachineBody));

            ITypeSymbol elementType = Context.Instance.ObjectType;
            if (method.ReturnType is INamedTypeSymbol && ((INamedTypeSymbol)method.ReturnType).IsGenericType)
            {
                var genericType = (INamedTypeSymbol)method.ReturnType;
                genericType = genericType.OriginalDefinition;
                if (Equals(genericType, Context.Instance.IEnumerableT))
                    elementType = method.ReturnType.GetGenericArgument(Context.Instance.IEnumerableT, 0);
                else if (Equals(genericType, Context.Instance.IEnumeratorT))
                    elementType = method.ReturnType.GetGenericArgument(Context.Instance.IEnumeratorT, 0);                
            }

            // Declare state machine fields
            var @this = stateMachineBody.Local(BaseStateGenerator.@this, Js.This());
            stateMachineBody.Local(BaseStateGenerator.state, Js.Primitive(0));
            var stateMachine = stateMachineBody.Local(BaseStateGenerator.stateMachine, CreateObject(Context.Instance.YieldIterator.Construct(elementType).Constructors.Single()));
//            var current = stateMachineBody.Local(YieldStateGenerator2.current, DefaultValue(elementType));
//            var isStarted = stateMachineBody.Local("$isStarted", Js.Primitive(false));

            // Create state generator and generate states
            var stateGenerator = new YieldStateGenerator(x => transformer, node, stateMachineBody, this, method);
            stateGenerator.GenerateStates();
            var rootState = stateGenerator.TopState;

            // Called when the initial method needs to return the enumerator, and also when cloning.

            // Declare the moveNext function
            var moveNextBody = Js.Block();
            var moveNext = stateMachineBody.Local(BaseStateGenerator.moveNext, Js.Function().Body(moveNextBody));
            moveNextBody.Add(Js.Label("$top", Js.While(Js.Primitive(true), Js.Block(stateGenerator.GenerateSwitch(rootState), Js.Primitive(false).Return()))));
            stateMachineBody.Add(MapInterfaceMethod(stateMachine.GetReference(), Context.Instance.YieldIteratorDoMoveNext, Js.Function().Body(moveNext.GetReference().Member("call").Invoke(@this.GetReference()).Return())));

            // Declare the clone function
            var cloneBody = Js.Block((stateMachineFunc.GetReference().Member("call").Invoke(@this.GetReference()).Return()));
            stateMachineBody.Add(MapInterfaceMethod(stateMachine.GetReference(), Context.Instance.YieldIteratorClone, Js.Function().Body(cloneBody)));

            // Generate the GetEnumerator method, which looks something like:
            // if ($isStarted) 
            //     return this.Clone().GetEnumerator();
            // else
            // {
            //     $isStarted = true;
            //     return this;
            // }
/*
            var getEnumeratorBody = Js.Block();
            var getEnumerator = stateMachineBody.Local("$getEnumerator", Js.Function().Body(getEnumeratorBody));
            getEnumeratorBody.Add(Js.If(
                isStarted.GetReference(), 
                Invoke(clone.GetReference().Invoke(), Context.Instance.IEnumerableTGetEnumerator).Return(),
                Js.Block(isStarted.SetReference().Assign(Js.Primitive(true)).Express(), stateMachine.GetReference().Return())
            ));
*/


/*
            ImplementInterfaceOnAdhocObject(stateMachineBody, stateMachine, Context.Instance.IEnumerable, new Dictionary<IMethodSymbol, JsExpression>
            {
                { Context.Instance.IEnumerableGetEnumerator, Js.Function().Body(getEnumerator.GetReference().Member("call").Invoke(@this.GetReference()).Return()) }
            });
            ImplementInterfaceOnAdhocObject(stateMachineBody, stateMachine, Context.Instance.IEnumerableT, new Dictionary<IMethodSymbol, JsExpression>
            {
                { Context.Instance.IEnumerableTGetEnumerator, stateMachine.GetReference().Member(Context.Instance.IEnumerableGetEnumerator.GetMemberName()) }
            });
            ImplementInterfaceOnAdhocObject(stateMachineBody, stateMachine, Context.Instance.IEnumerator, new Dictionary<IMethodSymbol, JsExpression>
            {
                { Context.Instance.IEnumeratorMoveNext, Js.Function().Body(moveNext.GetReference().Member("call").Invoke(@this.GetReference()).Return()) },
                { Context.Instance.IEnumeratorCurrent.GetMethod, Js.Function().Body(current.GetReference().Return()) },
                { Context.Instance.IEnumeratorReset, Js.Function() }
            });
            ImplementInterfaceOnAdhocObject(stateMachineBody, stateMachine, Context.Instance.IEnumeratorT, new Dictionary<IMethodSymbol, JsExpression>
            {
                { Context.Instance.IEnumeratorTCurrent.GetMethod, Js.Function().Body(current.GetReference().Return()) }
            });
*/

            // The state machine function will be invoked by the outer body.  It will expect the task 
            // to be returned for non-void async methods.  This task will be returned to the original 
            // caller of the async method.
            stateMachineBody.Return(stateMachine.GetReference());

            block.Add(stateMachineFunc.GetReference().Member("call").Invoke(Js.This()).Return());

            return block;
        }
示例#6
0
文件: Idioms.cs 项目: x335/WootzJs
        private JsExpression CreateMethodInfo(IMethodSymbol method, bool constructor = false)
        {
            JsExpression methodAttributes;
            switch (method.DeclaredAccessibility)
            {
                case Accessibility.Public:
                    methodAttributes = GetEnumValue(Context.Instance.MethodAttributesPublic);
                    break;
                case Accessibility.Internal:
                    methodAttributes = GetEnumValue(Context.Instance.MethodAttributesAssembly);
                    break;
                case Accessibility.Private:
                    methodAttributes = GetEnumValue(Context.Instance.MethodAttributesPrivate);
                    break;
                case Accessibility.Protected:
                    methodAttributes = GetEnumValue(Context.Instance.MethodAttributesFamily);
                    break;
                case Accessibility.ProtectedOrInternal:
                    methodAttributes = GetEnumValue(Context.Instance.MethodAttributesFamORAssem);
                    break;
                default:
                    throw new Exception();
            }
            if (method.IsStatic)
            {
                methodAttributes = EnumBitwise(SyntaxKind.BitwiseOrExpression, Context.Instance.MethodAttributes, 
                    methodAttributes, GetEnumValue(Context.Instance.MethodAttributesStatic));
            }

            var returnType = method.ReturnType;

            JsExpression info = constructor ?
                CreateObject(Context.Instance.ConstructorInfoConstructor,
                    Js.Primitive(method.GetMemberName()),
                    GetMethodFunction(method, true),
                    CreateParameterInfos(method.Parameters.ToArray()),
                    methodAttributes,
                    CreateAttributes(method)) :
                CreateObject(Context.Instance.MethodInfoConstructor,
                    Js.Primitive(method.MetadataName),
                    GetMethodFunction(method, true),
                    CreateParameterInfos(method.Parameters.ToArray()),
                    Type(returnType),
                    methodAttributes,
                    CreateAttributes(method));

            if (method.TypeParameters.Any())
            {
                var block = new JsBlockStatement();
                foreach (var typeParameter in method.TypeParameters)
                {
                    block.Local(
                        typeParameter.Name, 
                        Js.Reference(SpecialNames.DefineTypeParameter).Invoke(
                            Js.Reference(SpecialNames.Assembly),
                            Js.Primitive(typeParameter.Name), 
                            Type(typeParameter.BaseType ?? Context.Instance.ObjectType, true)));
                }
                block.Return(info);
                info = Wrap(block);
            }

            return info;
        }
示例#7
0
文件: Idioms.cs 项目: x335/WootzJs
        /// <summary>
        /// This generates the entire state machine as an inline function.  State machine fields are represented
        /// as closed variables of an outer function.  The actual "MoveNext" function is an inner function.
        /// </summary>
        public JsBlockStatement GenerateAsyncMethod(CSharpSyntaxNode node, IMethodSymbol method, Action<BaseStateGenerator, JsTransformer> nodeAcceptor = null)
        {
            var block = new JsBlockStatement();
            var stateMachineBody = Js.Block();
            var stateMachine = block.Local(BaseStateGenerator.stateMachine, Js.Function().Body(stateMachineBody));

            // Declare state machine fields
            var @this = stateMachineBody.Local(BaseStateGenerator.@this, Js.This());
            var state = stateMachineBody.Local(BaseStateGenerator.state, Js.Primitive(0));
            var builder = stateMachineBody.Local(AsyncStateGenerator.builder, InvokeStatic(GetAsyncMethodBuilder(method)));

            // Start up the async process via a call to the builder's Start method.
            var moveNextBody = Js.Block();
            var moveNext = stateMachineBody.Local(BaseStateGenerator.moveNext, Js.Function().Body(moveNextBody));

            // Create state generator and generate states
            var stateGenerator = new AsyncStateGenerator(this, stateMachineBody, node, method, nodeAcceptor);
            stateGenerator.GenerateStates();
            var rootState = stateGenerator.TopState;

            // Implement moveNext
            var moveNextTry = Js.Try();
            moveNextBody.Add(moveNextTry);
            moveNextTry.Body = Js.Block(
                Js.Label("$top", Js.While(Js.Primitive(true), Js.Block(stateGenerator.GenerateSwitch(rootState), Js.Break())))
            );
            var moveNextCatchException = Js.Variable("$ex");
            moveNextTry.Catch(moveNextCatchException);
            moveNextTry.Catch.Body = Js.Block(
                state.SetReference().Assign(Js.Primitive(-1)).Express(),
                builder.GetReference().Member("SetException").Invoke(moveNextCatchException.GetReference()).Express(),
                Js.Return()
            );

            // Ensure the stateMachine function implements IAsyncStateMachine
            ImplementInterfaceOnAdhocObject(stateMachineBody, stateMachine, Context.Instance.IAsyncStateMachine, new Dictionary<IMethodSymbol, JsExpression>
            {
                { Context.Instance.IAsyncStateMachineMoveNext, Js.Function().Body(moveNext.GetReference().Member("call").Invoke(@this.GetReference()).Return()) },
                { Context.Instance.IAsyncStateMachineSetStateMachine, Js.Null() }
            });

            stateMachineBody.Express(builder.GetReference().Member("TrueStart").Invoke(stateMachine.GetReference()));

            // The state machine function will be invoked by the outer body.  It will expect the task 
            // to be returned for non-void async methods.  This task will be returned to the original 
            // caller of the async method.
            if (!method.ReturnsVoid)
                stateMachineBody.Return(builder.GetReference().Member("get_Task").Invoke());

            var invokeStateMachine = stateMachine.GetReference().Member("call").Invoke(Js.This());
            if (!method.ReturnsVoid)
                block.Add(invokeStateMachine.Return());
            else
                block.Add(invokeStateMachine.Express());

            return block;
        }
示例#8
0
文件: Idioms.cs 项目: x335/WootzJs
        public bool TryApplyRefAndOutParametersAfterInvocation(IMethodSymbol method, JsInvocationExpression invocation, out JsExpression result, List<JsStatement> prependers, List<JsStatement> appenders)
        {
            // Finishing special handling of ref/out parameters -- doing the actual function wrapping here now that we
            // have the invocation.
            if (method.Parameters.Any(x => x.RefKind != RefKind.None))
            {
                // It's a ref or out parameter, we need somewhere to store the value.
                var invocationStage = new JsBlockStatement();
                foreach (var statement in prependers)
                    invocationStage.Add(statement);
                invocationStage.Local("$result$", invocation);
                foreach (var statement in appenders)
                    invocationStage.Add(statement);
                invocationStage.Return(Js.Reference("$result$"));

                result = Wrap(invocationStage);
                return true;
            }            
            result = null;
            return false;
        }
示例#9
0
文件: Idioms.cs 项目: x335/WootzJs
 public bool TryAsExpression(SyntaxKind type, ISymbol leftSymbol, ISymbol rightSymbol, JsExpression left, JsExpression right, out JsExpression result)
 {
     if (type == SyntaxKind.AsExpression)
     {
         var operand = (ITypeSymbol)rightSymbol;
         var asBody = new JsBlockStatement();
         var asVariable = Js.Variable("$as$", left);
         asBody.Local(asVariable);
         var condition = Type(Context.Instance.TypeType)
             .Member("prototype")
             .Member(Context.Instance.TypeIsInstanceOfType.GetMemberName())
             .Member("call")
             .Invoke(Type(operand).Member(SpecialNames.GetTypeFromType).Invoke(), asVariable.GetReference());
         asBody.If(Js.Not(condition), asVariable.GetReference().Assign(Js.Null()));
         asBody.Return(asVariable.GetReference());
         result = Wrap(asBody);
         return true;
     }
     result = null;
     return false;
 }
示例#10
0
文件: Idioms.cs 项目: x335/WootzJs
        public bool TryCharUnaryExpression(SyntaxKind type, TypeInfo operandType, JsExpression operand, out JsExpression result)
        {
            if (Equals(operandType.Type, Context.Instance.Char))
            {
                switch (type)
                {
                    case SyntaxKind.PostDecrementExpression:
                    case SyntaxKind.PostIncrementExpression:
                    {
                        var old = Js.Variable("$old", operand);

                        var op = type == SyntaxKind.PostDecrementExpression ? JsBinaryOperator.Subtract : JsBinaryOperator.Add;
                        result = Js.Binary(
                            op, 
                            old.GetReference().Member("charCodeAt").Invoke(Js.Primitive(0)),
                            Js.Primitive(1)
                        );
                        result = operand.Assign(Js.Reference("String").Member("fromCharCode").Invoke(result));

                        var block = new JsBlockStatement();
                        block.Local(old);
                        block.Express(result);
                        block.Return(old.GetReference());
                        result = Wrap(block);

                        return true;
                    }
                    case SyntaxKind.PreDecrementExpression:
                    case SyntaxKind.PreIncrementExpression:
                    {
                        var op = type == SyntaxKind.PreDecrementExpression ? JsBinaryOperator.Subtract : JsBinaryOperator.Add;
                        result = Js.Binary(
                            op, 
                            operand.Member("charCodeAt").Invoke(Js.Primitive(0)),
                            Js.Primitive(1)
                        );
                        result = operand.Assign(Js.Reference("String").Member("fromCharCode").Invoke(result));
                        return true;
                    }
                }
            }
            result = null;
            return false;
        }
示例#11
0
文件: Idioms.cs 项目: x335/WootzJs
        public JsInvocationExpression CreateMulticastDelegate(JsExpression target, JsExpression invocationList)
        {
            var delegateBody = new JsBlockStatement();
            var list = Js.Variable("$invocationList", invocationList);
            var i = Js.Variable("$i", Js.Primitive(0));
            delegateBody.Add(
                Js.For(
                    i, 
                    i.GetReference().LessThan(list.GetReference().Member("length")), 
                    i.GetReference().Increment()
                )
                .Body(list.GetReference().Index(i.GetReference()).Member("apply").Invoke(Js.Null(), Js.Reference("arguments")).Express()));

            var delegateExpression = Js.Function();
            delegateExpression.Body(delegateBody);
            var delegateVariable = Js.Variable("$delegate$", delegateExpression);

            var delegateType = invocationList.Index(Js.Primitive(0)).Member(SpecialNames.TypeField);

            var wrapper = new JsBlockStatement();
            wrapper.Local(list);
            wrapper.Local(delegateVariable);
            wrapper.Assign(delegateVariable.GetReference().Member("prototype"), Js.New(Type(Context.Instance.MulticastDelegateType)));
            wrapper.Invoke(Type(Context.Instance.ObjectType).Member(SpecialNames.TypeInitializer), delegateVariable.GetReference(), delegateVariable.GetReference());
            wrapper.Invoke(Type(Context.Instance.DelegateType).Member(SpecialNames.TypeInitializer), delegateVariable.GetReference(), delegateVariable.GetReference());
            wrapper.Invoke(Type(Context.Instance.MulticastDelegateType).Member(SpecialNames.TypeInitializer), delegateVariable.GetReference(), delegateVariable.GetReference());
            wrapper.Invoke(delegateType.Member(SpecialNames.TypeInitializer), delegateVariable.GetReference(), delegateVariable.GetReference());
            wrapper.Express(InvokeMethodAs(
                Context.Instance.MulticastDelegateConstructor, 
                delegateVariable.GetReference(), 
                target, 
                list.GetReference()));
            wrapper.Assign(delegateVariable.GetReference().Member(SpecialNames.TypeField), delegateType);
            wrapper.Return(delegateVariable.GetReference());

            return Wrap(wrapper);
        }