예제 #1
0
        private static void GenerateResources(ScriptGenerator generator, ResourcesSymbol resourcesSymbol)
        {
            ScriptTextWriter writer        = generator.Writer;
            string           resourcesName = resourcesSymbol.FullGeneratedName;

            writer.Write("var ");
            writer.Write(resourcesName);
            writer.WriteLine(" = {");
            writer.Indent++;

            bool firstValue = true;

            foreach (FieldSymbol member in resourcesSymbol.Members)
            {
                Debug.Assert(member.Value is string);

                if (firstValue == false)
                {
                    writer.Write(",");
                    writer.WriteLine();
                }

                writer.Write(member.GeneratedName);
                writer.Write(": ");
                writer.Write(Utility.QuoteString((string)member.Value));

                firstValue = false;
            }

            writer.Indent--;
            writer.WriteLine();
            writer.Write("};");
            writer.WriteLine();
        }
예제 #2
0
        private static void GenerateInterfaceRegistrationScript(ScriptGenerator generator,
                                                                InterfaceSymbol interfaceSymbol)
        {
            ScriptTextWriter writer = generator.Writer;

            writer.Write($"{DSharpStringResources.ScriptExportMember("defineInterface")}(");
            writer.Write(interfaceSymbol.FullGeneratedName);

            if (interfaceSymbol.Interfaces != null)
            {
                writer.Write(", [");
                bool first = true;

                foreach (InterfaceSymbol inheritedInterface in interfaceSymbol.Interfaces)
                {
                    if (!first)
                    {
                        writer.Write(", ");
                    }

                    writer.Write(inheritedInterface.FullGeneratedName);
                    first = false;
                }

                writer.Write("]");
            }

            writer.Write(")");
        }
예제 #3
0
        private static void GenerateThrowStatement(ScriptGenerator generator, MemberSymbol symbol,
                                                   ThrowStatement statement)
        {
            ScriptTextWriter writer = generator.Writer;

            writer.Write("throw ");
            ExpressionGenerator.GenerateExpression(generator, symbol, statement.Value);
            writer.WriteLine(";");
        }
예제 #4
0
        private static void GeneratePropertyComment(ScriptTextWriter writer, PropertySymbol propertySymbol)
        {
            GenerateSummaryComment(writer, propertySymbol);

            writer.Write("/// <value");

            GenerateTypeAttributes(writer, propertySymbol.AssociatedType);

            writer.WriteLine("></value>");
        }
예제 #5
0
        private static void WriteParameters(MethodSymbol methodSymbol, ScriptTextWriter writer)
        {
            if (methodSymbol.Parameters != null)
            {
                int paramIndex = 0;

                foreach (ParameterSymbol parameterSymbol in methodSymbol.Parameters)
                {
                    if (paramIndex > 0)
                    {
                        writer.Write(", ");
                    }

                    writer.Write(parameterSymbol.GeneratedName);

                    paramIndex++;
                }
            }
        }
예제 #6
0
        private static void GenerateForStatement(ScriptGenerator generator, MemberSymbol symbol, ForStatement statement)
        {
            if (statement.Body == null)
            {
                return;
            }

            ScriptTextWriter writer = generator.Writer;

            writer.Write("for ");
            writer.Write("(");

            if (statement.Initializers != null)
            {
                ExpressionGenerator.GenerateExpressionList(generator, symbol, statement.Initializers);
            }
            else if (statement.Variables != null)
            {
                GenerateVariableDeclarations(generator, symbol, statement.Variables);
            }

            writer.Write("; ");

            if (statement.Condition != null)
            {
                ExpressionGenerator.GenerateExpression(generator, symbol, statement.Condition);
            }

            writer.Write("; ");

            if (statement.Increments != null)
            {
                ExpressionGenerator.GenerateExpressionList(generator, symbol, statement.Increments);
            }

            writer.WriteLine(") {");
            writer.Indent++;
            GenerateStatement(generator, symbol, statement.Body);
            writer.Indent--;
            writer.Write("}");
            writer.WriteLine();
        }
예제 #7
0
        private static void GenerateRecord(ScriptGenerator generator, RecordSymbol recordSymbol)
        {
            ScriptTextWriter writer     = generator.Writer;
            string           recordName = recordSymbol.FullGeneratedName;

            writer.Write("function ");
            writer.Write(recordName);
            writer.Write("(");

            ConstructorSymbol ctorSymbol = recordSymbol.Constructor;

            if (ctorSymbol?.Parameters != null)
            {
                bool firstParameter = true;

                foreach (ParameterSymbol parameterSymbol in ctorSymbol.Parameters)
                {
                    if (firstParameter == false)
                    {
                        writer.Write(", ");
                    }

                    writer.Write(parameterSymbol.GeneratedName);
                    firstParameter = false;
                }
            }

            writer.Write(") {");

            if (recordSymbol.Constructor != null)
            {
                writer.Indent++;
                writer.WriteLine();
                writer.WriteLine("var $o = {};");
                CodeGenerator.GenerateScript(generator, recordSymbol.Constructor);
                writer.Write("return $o;");
                writer.WriteLine();
                writer.Indent--;
            }
            else
            {
                writer.Write(" return {}; ");
            }

            writer.Write("}");
            writer.WriteLine();
        }
예제 #8
0
        private static void GenerateParameterComment(ScriptTextWriter writer, ParameterSymbol parameterSymbol)
        {
            writer.Write("/// <param name=\"{0}\"", parameterSymbol.GeneratedName);

            GenerateTypeAttributes(writer, parameterSymbol.ValueType);

            writer.WriteLine(">");

            GenerateFormattedComment(writer, parameterSymbol.Documentation);

            writer.WriteLine("/// </param>");
        }
예제 #9
0
        private static void GenerateEnumeration(ScriptGenerator generator, EnumerationSymbol enumSymbol)
        {
            ScriptTextWriter writer   = generator.Writer;
            string           enumName = enumSymbol.FullGeneratedName;

            writer.Write("var ");
            writer.Write(enumSymbol.FullGeneratedName);
            writer.Write(" = {");
            writer.Indent++;

            bool firstValue = true;

            foreach (MemberSymbol memberSymbol in enumSymbol.Members)
            {
                if (!(memberSymbol is EnumerationFieldSymbol fieldSymbol))
                {
                    continue;
                }

                if (firstValue == false)
                {
                    writer.Write(", ");
                }

                writer.WriteLine();
                writer.Write(fieldSymbol.GeneratedName);
                writer.Write(": ");

                if (enumSymbol.UseNamedValues)
                {
                    writer.Write(Utility.QuoteString(enumSymbol.CreateNamedValue(fieldSymbol)));
                }
                else
                {
                    writer.Write(fieldSymbol.Value);
                }

                firstValue = false;
            }

            writer.Indent--;
            writer.WriteLine();
            writer.Write("};");
            writer.WriteLine();
        }
예제 #10
0
        private static void GenerateReturnsComment(ScriptTextWriter writer, TypeSymbol typeSymbol)
        {
            if (IsVoid(typeSymbol))
            {
                return;
            }

            writer.Write("/// <returns");

            GenerateTypeAttributes(writer, typeSymbol);

            writer.WriteLine("></returns>");
        }
예제 #11
0
        private static void GenerateExpressionStatement(ScriptGenerator generator, MemberSymbol symbol,
                                                        ExpressionStatement statement)
        {
            ScriptTextWriter writer = generator.Writer;

            ExpressionGenerator.GenerateExpression(generator, symbol, statement.Expression);

            if (statement.IsFragment == false)
            {
                writer.Write(";");
                writer.WriteLine();
            }
        }
예제 #12
0
        private static void GenerateBaseInitializerExpression(ScriptGenerator generator, MemberSymbol symbol,
                                                              BaseInitializerExpression expression)
        {
            ScriptTextWriter writer = generator.Writer;

            Debug.Assert(symbol.Parent is ClassSymbol);

            ClassSymbol baseClass = ((ClassSymbol)symbol.Parent).BaseClass;

            Debug.Assert(baseClass != null);

            writer.Write(baseClass.FullGeneratedName);
            writer.Write(".call(this");

            if (expression.Parameters != null)
            {
                writer.Write(", ");
                GenerateExpressionList(generator, symbol, expression.Parameters);
            }

            writer.Write(")");
        }
예제 #13
0
        private static void GenerateProperty(ScriptGenerator generator, string typeName, PropertySymbol propertySymbol)
        {
            if (propertySymbol.IsAbstract)
            {
                return;
            }

            ScriptTextWriter writer = generator.Writer;

            bool instanceMember = true;

            if ((propertySymbol.Visibility & MemberVisibility.Static) != 0)
            {
                instanceMember = false;
            }

            if (propertySymbol.HasGetter)
            {
                GeneratePropertyGetter(generator, typeName, propertySymbol, writer, instanceMember);
            }

            if (propertySymbol.HasSetter)
            {
                if (instanceMember && propertySymbol.HasGetter)
                {
                    writer.WriteLine(",");
                }

                GeneratePropertySetter(generator, typeName, propertySymbol, writer, instanceMember);
            }

            if (propertySymbol.Visibility.HasFlag(MemberVisibility.Static) && propertySymbol.IsAutoProperty())
            {
                writer.Write(DSharpStringResources.ScriptExportMember("defineProperty"));
                writer.Write($"({((ClassSymbol)propertySymbol.Parent).FullGeneratedName}, '{propertySymbol.GeneratedName}');");
                writer.WriteLine();
            }
        }
예제 #14
0
        private static void GenerateSwitchStatement(ScriptGenerator generator, MemberSymbol symbol,
                                                    SwitchStatement statement)
        {
            ScriptTextWriter writer = generator.Writer;

            writer.Write("switch (");
            ExpressionGenerator.GenerateExpression(generator, symbol, statement.Condition);
            writer.WriteLine(") {");
            writer.Indent++;

            foreach (SwitchGroup group in statement.Groups)
            {
                if (group.Cases != null)
                {
                    foreach (Expression caseExpression in group.Cases)
                    {
                        writer.Write("case ");
                        ExpressionGenerator.GenerateExpression(generator, symbol, caseExpression);
                        writer.WriteLine(":");
                    }
                }

                if (group.IncludeDefault)
                {
                    writer.WriteLine("default:");
                }

                writer.Indent++;
                foreach (Statement childStatement in group.Statements)
                {
                    GenerateStatement(generator, symbol, childStatement);
                }
                writer.Indent--;
            }

            writer.Indent--;
            writer.WriteLine("}");
        }
예제 #15
0
        private static void WriteInterfaces(ScriptTextWriter writer, ICollection <InterfaceSymbol> interfaces)
        {
            if (interfaces is null)
            {
                return;
            }
            writer.Write(", [");
            bool first = true;

            foreach (InterfaceSymbol inheritedInterface in interfaces)
            {
                if (!first)
                {
                    writer.Write(", ");
                }

                WriteTypeReference(writer, inheritedInterface);

                first = false;
            }

            writer.Write("]");
        }
예제 #16
0
        public static void GenerateClassConstructorScript(ScriptGenerator generator, ClassSymbol classSymbol)
        {
            // NOTE: This is emitted last in the script file, and separate from the initial class definition
            //       because it needs to be emitted after the class registration.

            foreach (MemberSymbol memberSymbol in classSymbol.Members)
            {
                if (memberSymbol.Type == SymbolType.Field &&
                    (memberSymbol.Visibility & MemberVisibility.Static) != 0)
                {
                    FieldSymbol fieldSymbol = (FieldSymbol)memberSymbol;

                    if (fieldSymbol.IsConstant &&
                        (memberSymbol.Visibility & (MemberVisibility.Public | MemberVisibility.Protected)) == 0)
                    {
                        // PrivateInstance/Internal constant fields are omitted since they have been inlined
                        continue;
                    }

                    if (fieldSymbol.HasInitializer)
                    {
                        MemberGenerator.GenerateScript(generator, memberSymbol);
                    }
                }
            }

            if (classSymbol.StaticConstructor != null)
            {
                ScriptTextWriter writer = generator.Writer;

                SymbolImplementation implementation = classSymbol.StaticConstructor.Implementation;
                bool requiresFunctionScope          = implementation.DeclaresVariables;

                if (requiresFunctionScope)
                {
                    writer.WriteLine("(function() {");
                    writer.Indent++;
                }

                CodeGenerator.GenerateScript(generator, classSymbol.StaticConstructor);

                if (requiresFunctionScope)
                {
                    writer.Indent--;
                    writer.Write("})();");
                    writer.WriteLine();
                }
            }
        }
예제 #17
0
        private static void GenerateWhileStatement(ScriptGenerator generator, MemberSymbol symbol,
                                                   WhileStatement statement)
        {
            if (statement.Body == null)
            {
                return;
            }

            ScriptTextWriter writer = generator.Writer;

            if (statement.PreCondition)
            {
                writer.Write("while (");
                ExpressionGenerator.GenerateExpression(generator, symbol, statement.Condition);
                writer.WriteLine(") {");
            }
            else
            {
                writer.WriteLine("do {");
            }

            writer.Indent++;
            GenerateStatement(generator, symbol, statement.Body);
            writer.Indent--;

            if (statement.PreCondition)
            {
                writer.WriteLine("}");
            }
            else
            {
                writer.Write("} while (");
                ExpressionGenerator.GenerateExpression(generator, symbol, statement.Condition);
                writer.WriteLine(");");
            }
        }
예제 #18
0
        private static void GenerateReturnStatement(ScriptGenerator generator, MemberSymbol symbol,
                                                    ReturnStatement statement)
        {
            ScriptTextWriter writer = generator.Writer;

            if (statement.Value != null)
            {
                writer.Write("return ");
                ExpressionGenerator.GenerateExpression(generator, symbol, statement.Value);
                writer.WriteLine(";");
            }
            else
            {
                writer.WriteLine("return;");
            }
        }
예제 #19
0
        private static void GeneratePropertyGetter(ScriptGenerator generator, string typeName,
                                                   PropertySymbol propertySymbol, ScriptTextWriter writer,
                                                   bool instanceMember)
        {
            if (instanceMember)
            {
                writer.Write("$get_");
                writer.Write(propertySymbol.GeneratedName);
                writer.Write(": ");
            }
            else
            {
                writer.Write($"{DSharpStringResources.ScriptExportMember("createPropertyGet")}(");
                writer.Write(typeName);
                writer.Write(", '");
                writer.Write(propertySymbol.GeneratedName);
                writer.Write("', ");
            }

            writer.WriteLine("function() {");
            writer.Indent++;

            if (generator.Options.EnableDocComments)
            {
                DocCommentGenerator.GenerateComment(generator, propertySymbol);
            }

            CodeGenerator.GenerateScript(generator, propertySymbol, /* getter */ true);
            writer.Indent--;
            writer.Write("}");

            if (instanceMember == false)
            {
                writer.WriteLine(");");
            }
        }
예제 #20
0
        private static void GenerateTypeAttributes(ScriptTextWriter writer, TypeSymbol typeSymbol)
        {
            if (IsDomElement(typeSymbol))
            {
                writer.Write(" type=\"Object\" domElement=\"true\"");
            }
            else
            {
                writer.Write(" type=\"{0}\"", typeSymbol.FullGeneratedName);
            }

            if (IsInteger(typeSymbol))
            {
                writer.Write(" integer=\"true\"");
            }

            if (typeSymbol.IsNativeArray)
            {
                ClassSymbol classSymbol = (ClassSymbol)typeSymbol;

                TypeSymbol elementTypeSymbol = classSymbol.Indexer.AssociatedType;

                if (IsDomElement(elementTypeSymbol))
                {
                    writer.Write(" elementType=\"Object\" elementDomElement=\"true\"");
                }
                else
                {
                    writer.Write(" elementType=\"{0}\"", elementTypeSymbol.GeneratedName);
                }

                if (IsInteger(elementTypeSymbol))
                {
                    writer.Write(" elementInteger=\"true\"");
                }
            }
        }
예제 #21
0
        private static void WriteTypeReference(ScriptTextWriter writer, TypeSymbol typeSymbol, string typePrefix = "")
        {
            typeSymbol = GetParameterType(typeSymbol);

            if (typeSymbol.IsGeneric && typeSymbol.GenericArguments is IList <TypeSymbol> )
            {
                if (typeSymbol.IgnoreGenericTypeArguments)
                {
                    writer.Write(typePrefix);
                    writer.Write(typeSymbol.FullGeneratedName);
                }
                else if (typeSymbol.GenericArguments.Any(p => p is GenericParameterSymbol gp && gp.IsTypeParameter))
                {
                    writer.Write($"ss.makeMappedGenericTemplate({typePrefix}{typeSymbol.FullGeneratedName}, ");
                    ScriptGeneratorExtensions.WriteGenericTypeArguments(writer.Write, typeSymbol.GenericArguments, typeSymbol.GenericParameters, writeNameMap: true);
                    writer.Write(")");
                }
                else
                {
                    writer.Write($"ss.getGenericConstructor({typePrefix}{typeSymbol.FullGeneratedName}, ");
                    ScriptGeneratorExtensions.WriteGenericTypeArguments(writer.Write, typeSymbol.GenericArguments, typeSymbol.GenericParameters);
                    writer.Write(")");
                }
            }
예제 #22
0
        private static void GenerateForInStatement(ScriptGenerator generator, MemberSymbol symbol,
                                                   ForInStatement statement)
        {
            ScriptTextWriter writer        = generator.Writer;
            TypeSymbol       evaluatedType = statement.CollectionExpression.EvaluatedType;

            if (statement.IsDictionaryEnumeration)
            {
                if (statement.DictionaryVariable != null)
                {
                    writer.Write("var ");
                    writer.Write(statement.DictionaryVariable.GeneratedName);
                    writer.Write(" = ");
                    ExpressionGenerator.GenerateExpression(generator, symbol, statement.CollectionExpression);
                    writer.Write(";");
                    writer.WriteLine();
                }

                writer.Write("for (var ");
                writer.Write(statement.LoopVariable.GeneratedName);
                writer.Write(" in ");

                if (statement.DictionaryVariable != null)
                {
                    writer.Write(statement.DictionaryVariable.GeneratedName);
                }
                else
                {
                    ExpressionGenerator.GenerateExpression(generator, symbol, statement.CollectionExpression);
                }

                writer.WriteLine(") {");
                writer.Indent++;
                writer.Write("var ");
                writer.Write(statement.ItemVariable.GeneratedName);
                writer.Write(" = { key: ");
                writer.Write(statement.LoopVariable.GeneratedName);
                writer.Write(", value: ");

                if (statement.DictionaryVariable != null)
                {
                    writer.Write(statement.DictionaryVariable.GeneratedName);
                }
                else
                {
                    ExpressionGenerator.GenerateExpression(generator, symbol, statement.CollectionExpression);
                }

                writer.Write("[");
                writer.Write(statement.LoopVariable.GeneratedName);
                writer.WriteLine("] };");
                GenerateStatement(generator, symbol, statement.Body);
                writer.Indent--;
                writer.WriteLine("}");
            }
            else if (evaluatedType.IsNativeArray || evaluatedType.IsListType())
            {
                string dataSourceVariableName = statement.LoopVariable.GeneratedName;
                string indexVariableName      = dataSourceVariableName + "_index";

                // var $$ = ({CollectionExpression});
                writer.Write("var " + dataSourceVariableName + " = (");
                ExpressionGenerator.GenerateExpression(generator, symbol, statement.CollectionExpression);
                writer.WriteLine(");");

                // for(var items_index = 0; items_index < items.length; ++items_index) {
                writer.WriteLine("for(var " + indexVariableName + " = 0; " + indexVariableName + " < " + dataSourceVariableName + ".length; ++" + indexVariableName + ") {");

                ++writer.Indent;

                if (evaluatedType.IsNativeArray)
                {
                    // var i = items[items_index];
                    writer.WriteLine("var " + statement.ItemVariable.GeneratedName + " = " + dataSourceVariableName + "[" + indexVariableName + "];");
                }
                else
                {
                    // var i = ss.getItem(items, items_index);
                    writer.WriteLine("var " + statement.ItemVariable.GeneratedName + " = ss.getItem(" + dataSourceVariableName + ", " + indexVariableName + ");");
                }

                GenerateStatement(generator, symbol, statement.Body);

                --writer.Indent;
                writer.WriteLine("}");
            }
            else
            {
                writer.Write("var ");
                writer.Write(statement.LoopVariable.GeneratedName);
                writer.Write(" = ");

                writer.Write($"{DSharpStringResources.ScriptExportMember("enumerate")}(");
                ExpressionGenerator.GenerateExpression(generator, symbol, statement.CollectionExpression);
                writer.Write(");");

                writer.WriteLine();

                writer.Write("while (");
                writer.Write(statement.LoopVariable.GeneratedName);
                writer.WriteLine(".moveNext()) {");
                writer.Indent++;

                writer.Write("var ");
                writer.Write(statement.ItemVariable.GeneratedName);
                writer.Write(" = ");
                writer.Write(statement.LoopVariable.GeneratedName);
                writer.Write(".current;");
                writer.WriteLine();

                GenerateStatement(generator, symbol, statement.Body);

                writer.Indent--;
                writer.Write("}");
                writer.WriteLine();
            }
        }
예제 #23
0
        private static void GenerateClassConstructor(ScriptGenerator generator, ClassSymbol classSymbol, ScriptTextWriter writer, string name)
        {
            writer.Write("function ");
            writer.Write(name);
            writer.Write("(");

            if (classSymbol.Constructor != null && classSymbol.Constructor.Parameters != null)
            {
                bool firstParameter = true;

                foreach (ParameterSymbol parameterSymbol in classSymbol.Constructor.Parameters)
                {
                    if (firstParameter == false)
                    {
                        writer.Write(", ");
                    }

                    writer.Write(parameterSymbol.GeneratedName);
                    firstParameter = false;
                }
            }

            writer.WriteLine(") {");
            writer.Indent++;

            if (generator.Options.EnableDocComments)
            {
                DocCommentGenerator.GenerateComment(generator, classSymbol);
            }

            foreach (var property in GetNonReadonlyAutoProperties(classSymbol))
            {
                writer.Write(DSharpStringResources.ScriptExportMember("defineProperty"));
                writer.Write($"(this, '{property.GeneratedName}');");
                writer.WriteLine();
            }

            foreach (MemberSymbol memberSymbol in classSymbol.Members)
            {
                if (memberSymbol.Type == SymbolType.Field &&
                    (memberSymbol.Visibility & MemberVisibility.Static) == 0)
                {
                    FieldSymbol fieldSymbol = (FieldSymbol)memberSymbol;

                    if (fieldSymbol.HasInitializer)
                    {
                        writer.Write("this.");
                        writer.Write(fieldSymbol.GeneratedName);
                        writer.Write(" = ");
                        CodeGenerator.GenerateScript(generator, fieldSymbol);
                        writer.Write(";");
                        writer.WriteLine();
                    }
                }
            }

            if (classSymbol.Constructor != null)
            {
                CodeGenerator.GenerateScript(generator, classSymbol.Constructor);
            }
            else if (classSymbol.BaseClass != null)
            {
                writer.Write(classSymbol.BaseClass.FullGeneratedName);
                writer.Write(".call(this);");
                writer.WriteLine();
            }

            writer.Indent--;
            writer.WriteLine("}");
        }
예제 #24
0
        private static void GenerateIndexer(ScriptGenerator generator, string typeName, PropertySymbol indexerSymbol)
        {
            if (indexerSymbol.IsAbstract)
            {
                return;
            }

            Debug.Assert((indexerSymbol.Visibility & MemberVisibility.Static) == 0);

            ScriptTextWriter writer = generator.Writer;

            writer.Write("get_");
            writer.Write(indexerSymbol.GeneratedName);
            writer.Write(": function(");

            for (int i = 0; i < indexerSymbol.Parameters.Count - 1; i++)
            {
                ParameterSymbol parameterSymbol = indexerSymbol.Parameters[i];

                if (i > 0)
                {
                    writer.Write(", ");
                }

                writer.Write(parameterSymbol.GeneratedName);
            }

            writer.WriteLine(") {");
            writer.Indent++;

            if (generator.Options.EnableDocComments)
            {
                DocCommentGenerator.GenerateComment(generator, indexerSymbol);
            }

            CodeGenerator.GenerateScript(generator, (IndexerSymbol)indexerSymbol, /* getter */ true);
            writer.Indent--;
            writer.Write("}");

            if (indexerSymbol.IsReadOnly == false)
            {
                writer.WriteLine(",");

                writer.Write("set_");
                writer.Write(indexerSymbol.GeneratedName);
                writer.Write(": function(");

                for (int i = 0; i < indexerSymbol.Parameters.Count; i++)
                {
                    ParameterSymbol parameterSymbol = indexerSymbol.Parameters[i];

                    if (i > 0)
                    {
                        writer.Write(", ");
                    }

                    writer.Write(parameterSymbol.GeneratedName);
                }

                writer.WriteLine(") {");
                writer.Indent++;

                if (generator.Options.EnableDocComments)
                {
                    DocCommentGenerator.GenerateComment(generator, indexerSymbol);
                }

                CodeGenerator.GenerateScript(generator, (IndexerSymbol)indexerSymbol, /* getter */ false);
                writer.Write("return ");
                writer.Write(indexerSymbol.Parameters[indexerSymbol.Parameters.Count - 1].GeneratedName);
                writer.WriteLine(";");
                writer.Indent--;
                writer.Write("}");
            }
        }
예제 #25
0
        private static void GenerateBinaryExpression(ScriptGenerator generator, MemberSymbol symbol,
                                                     BinaryExpression expression)
        {
            ScriptTextWriter writer = generator.Writer;

            if (expression.Operator == Operator.Equals)
            {
                if (expression.LeftOperand is PropertyExpression propExpression)
                {
                    Debug.Assert(propExpression.Type == ExpressionType.PropertySet);

                    if (propExpression.ObjectReference is BaseExpression)
                    {
                        ClassSymbol classSymbol = (ClassSymbol)symbol.Parent;
                        writer.Write($"{DSharpStringResources.ScriptExportMember("baseProperty")}(");
                        writer.Write(classSymbol.FullGeneratedName);
                        writer.Write(", '");
                        writer.Write(propExpression.Property.GeneratedName);
                        writer.Write("').set.call(");
                        writer.Write(generator.CurrentImplementation.ThisIdentifier);
                        writer.Write(", ");
                        GenerateExpression(generator, symbol, expression.RightOperand);
                        writer.Write(")");
                    }
                    else
                    {
                        GenerateExpression(generator, symbol, propExpression.ObjectReference);
                        writer.Write(".");
                        writer.Write(propExpression.Property.GeneratedName);
                        writer.Write(" = ");
                        GenerateExpression(generator, symbol, expression.RightOperand);
                    }

                    propExpression.Property.IncrementReferenceCount();
                    return;
                }

                if (expression.LeftOperand is IndexerExpression indexExpression)
                {
                    IndexerSymbol indexerSymbol = indexExpression.Indexer;

                    if (!indexerSymbol.UseScriptIndexer)
                    {
                        Debug.Assert(indexExpression.Type == ExpressionType.Indexer);

                        if (indexExpression.ObjectReference is BaseExpression objectReference)
                        {
                            writer.Write(objectReference.EvaluatedType.FullGeneratedName);
                            writer.Write(".prototype.set_");
                            writer.Write(indexerSymbol.GeneratedName);
                            writer.Write(".call(");
                            writer.Write(generator.CurrentImplementation.ThisIdentifier);
                            writer.Write(", ");
                            GenerateExpressionList(generator, symbol, indexExpression.Indices);
                            writer.Write(", ");
                            GenerateExpression(generator, symbol, expression.RightOperand);
                            writer.Write(")");
                        }
                        else
                        {
                            GenerateExpression(generator, symbol, indexExpression.ObjectReference);
                            writer.Write(".set_");
                            writer.Write(indexerSymbol.GeneratedName);
                            writer.Write("(");
                            GenerateExpressionList(generator, symbol, indexExpression.Indices);
                            writer.Write(", ");
                            GenerateExpression(generator, symbol, expression.RightOperand);
                            writer.Write(")");
                        }

                        indexExpression.Indexer.IncrementReferenceCount();
                        return;
                    }
                    else if (indexerSymbol.Parent is TypeSymbol typeSymbol && !typeSymbol.IsNativeArray)
                    {
                        writer.Write($"ss.setItem(");
                        GenerateExpression(generator, symbol, indexExpression.ObjectReference);
                        writer.Write(", ");
                        GenerateExpressionList(generator, symbol, indexExpression.Indices);
                        writer.Write(", ");
                        GenerateExpression(generator, symbol, expression.RightOperand);
                        writer.Write(")");

                        return;
                    }
                }
            }
            else if (expression.Operator == Operator.PlusEquals ||
                     expression.Operator == Operator.MinusEquals ||
                     expression.Operator == Operator.MultiplyEquals ||
                     expression.Operator == Operator.DivideEquals ||
                     expression.Operator == Operator.ModEquals ||
                     expression.Operator == Operator.BitwiseOrEquals ||
                     expression.Operator == Operator.BitwiseAndEquals ||
                     expression.Operator == Operator.BitwiseXorEquals ||
                     expression.Operator == Operator.ShiftLeftEquals ||
                     expression.Operator == Operator.ShiftRightEquals ||
                     expression.Operator == Operator.UnsignedShiftRightEquals)
            {
                if (expression.LeftOperand is PropertyExpression propExpression)
                {
                    Debug.Assert(propExpression.Type == ExpressionType.PropertyGet);

                    GenerateExpression(generator, symbol, propExpression.ObjectReference);
                    writer.Write(".");
                    writer.Write(propExpression.Property.GeneratedName);
                    writer.Write(" = ");
                    GenerateExpression(generator, symbol, propExpression.ObjectReference);
                    writer.Write(OperatorConverter.OperatorToString(expression.Operator - 1));
                    GenerateExpression(generator, symbol, expression.RightOperand);

                    propExpression.Property.IncrementReferenceCount();
                    return;
                }
            }
            else if (expression.Operator == Operator.Is ||
                     expression.Operator == Operator.As)
            {
                TypeExpression typeExpression = expression.RightOperand as TypeExpression;
                Debug.Assert(typeExpression != null);

                writer.Write(DSharpStringResources.ScriptExportMember(string.Empty));

                if (expression.Operator == Operator.Is)
                {
                    writer.Write("canCast(");
                }
                else
                {
                    writer.Write("safeCast(");
                }

                GenerateExpression(generator, symbol, expression.LeftOperand);

                writer.Write(", ");
                writer.Write(typeExpression.AssociatedType.FullGeneratedName);
                writer.Write(")");
                typeExpression.AssociatedType.IncrementReferenceCount();
                return;
            }
            else if (expression.Operator == Operator.EqualEqualEqual ||
                     expression.Operator == Operator.NotEqualEqual)
            {
                if (expression.RightOperand is LiteralExpression literalExpression)
                {
                    // Optimize generated script to perform loose equality checks for false-y values
                    // (null, false, 0, empty string)

                    // TODO: This should really be happening at compilation time, rather than generation
                    //       time. Because this is happening at generation time, we get something like
                    //       if (!!x) when if(x) would suffice just so we can get
                    //       foo(!!x) where foo is a method expecting a boolean.
                    //       Doing this at compilation time would allow handling if scenarios specially.

                    bool optimizable   = false;
                    bool checkForFalse = false;

                    if (literalExpression.Value is bool compareValue)
                    {
                        optimizable = true;

                        if (compareValue && expression.Operator == Operator.NotEqualEqual ||
                            !compareValue && expression.Operator == Operator.EqualEqualEqual)
                        {
                            checkForFalse = true;
                        }
                    }
                    else if (literalExpression.Value is int i && i == 0)
                    {
                        optimizable   = true;
                        checkForFalse = expression.Operator == Operator.EqualEqualEqual;
                    }
                    else if (literalExpression.Value is string s && s == string.Empty)
                    {
                        optimizable   = true;
                        checkForFalse = expression.Operator == Operator.EqualEqualEqual;
                    }

                    if (optimizable)
                    {
                        bool parenthesize = false;

                        writer.Write(checkForFalse ? "!" : "!!");

                        if (expression.LeftOperand.Parenthesized == false &&
                            (expression.LeftOperand.Type == ExpressionType.Binary ||
                             expression.LeftOperand.Type == ExpressionType.Conditional ||
                             expression.LeftOperand.Type == ExpressionType.InlineScript))
                        {
                            parenthesize = true;
                            writer.Write("(");
                        }

                        GenerateExpression(generator, symbol, expression.LeftOperand);

                        if (parenthesize)
                        {
                            writer.Write(")");
                        }

                        return;
                    }
                }
            }
예제 #26
0
        private static void GenerateClassConstructor(ScriptGenerator generator, ClassSymbol classSymbol, ScriptTextWriter writer, string name)
        {
            var ctorSymbol = classSymbol.Constructor;

            if (HasParamsModifier(ctorSymbol))
            {
                writer.Write($"var {name} = ss.namedFunction('{name}',");
                writer.Write($"{DSharpStringResources.ScriptExportMember("paramsGenerator")}(");
                writer.Write($"{ctorSymbol.GetGeneratedParamsCount()}, function");
            }
            else
            {
                writer.Write("function ");
                writer.Write(name);
            }

            writer.Write("(");

            if (ctorSymbol != null && ctorSymbol.Parameters != null)
            {
                bool firstParameter = true;

                foreach (ParameterSymbol parameterSymbol in ctorSymbol.Parameters)
                {
                    if (firstParameter == false)
                    {
                        writer.Write(", ");
                    }

                    writer.Write(parameterSymbol.GeneratedName);
                    firstParameter = false;
                }
            }

            writer.WriteLine(") {");
            writer.Indent++;

            if (generator.Options.EnableDocComments)
            {
                DocCommentGenerator.GenerateComment(generator, classSymbol);
            }

            foreach (var property in GetNonReadonlyAutoProperties(classSymbol))
            {
                writer.Write(DSharpStringResources.ScriptExportMember("defineProperty"));
                writer.Write($"(this, '{property.GeneratedName}', ");

                var initialValueExpression = Compiler.ImplementationBuilder.GetDefaultValueExpression(property.AssociatedType, property.SymbolSet);
                ExpressionGenerator.GenerateLiteralExpression(generator, property, initialValueExpression);

                writer.Write(");");
                writer.WriteLine();
            }

            foreach (MemberSymbol memberSymbol in classSymbol.Members)
            {
                if (memberSymbol.Type == SymbolType.Field &&
                    (memberSymbol.Visibility & MemberVisibility.Static) == 0)
                {
                    FieldSymbol fieldSymbol = (FieldSymbol)memberSymbol;

                    if (fieldSymbol.HasInitializer)
                    {
                        writer.Write("this.");
                        writer.Write(fieldSymbol.GeneratedName);
                        writer.Write(" = ");
                        CodeGenerator.GenerateScript(generator, fieldSymbol);
                        writer.Write(";");
                        writer.WriteLine();
                    }
                }
            }

            if (ctorSymbol != null)
            {
                CodeGenerator.GenerateScript(generator, ctorSymbol);
            }
            else if (classSymbol.BaseClass is ClassSymbol baseClass)
            {
                ExpressionGenerator.WriteFullTypeName(writer, baseClass);
                writer.WriteLine(".call(this);");
            }

            writer.Indent--;
            writer.WriteLine("}");

            if (HasParamsModifier(ctorSymbol))
            {
                writer.WriteLine($"));");
            }
        }
예제 #27
0
        private static void WriteConstructorParameters(ClassSymbol classSymbol, ScriptTextWriter writer)
        {
            if (classSymbol.Constructor?.Parameters is null)
            {
                writer.Write("[], ");
                return;
            }

            bool hasApplicationTypes = classSymbol.Constructor.Parameters
                                       .Select(p => p.ValueType)
                                       .Any(ShouldUseRegistry);

            if (hasApplicationTypes)
            {
                writer.Write("function (");
                writer.Write("registry");
                writer.Write(")");
                writer.Write(" { return ");
            }

            writer.Write("[");

            bool firstParameter = true;

            foreach (ParameterSymbol parameterSymbol in classSymbol.Constructor.Parameters)
            {
                if (firstParameter == false)
                {
                    writer.Write(", ");
                }

                TypeSymbol parameterType = parameterSymbol.ValueType;
                if (parameterType is GenericParameterSymbol)
                {
                    writer.Write($"'{parameterType.FullGeneratedName}'");
                }
                else
                {
                    if (ShouldUseRegistry(parameterType))
                    {
                        WriteTypeReference(writer, parameterType, "registry.");
                    }
                    else
                    {
                        WriteTypeReference(writer, parameterType);
                    }
                }
                firstParameter = false;
            }

            writer.Write("]");

            if (hasApplicationTypes)
            {
                writer.Write("}");
            }

            writer.Write(", ");
        }
예제 #28
0
        private static void GenerateClassRegistrationScript(ScriptGenerator generator, ClassSymbol classSymbol)
        {
            ScriptTextWriter writer = generator.Writer;

            //class definition
            writer.Write($"{DSharpStringResources.ScriptExportMember("defineClass")}(");
            writer.Write(classSymbol.FullGeneratedName);
            writer.Write(", ");

            if (classSymbol.IsStaticClass)
            {
                writer.Write("null, ");
            }
            else
            {
                writer.Write(classSymbol.FullGeneratedName);
                writer.Write("$, ");
            }

            //constructor params
            writer.Write("[");

            if (classSymbol.Constructor != null && classSymbol.Constructor.Parameters != null)
            {
                bool firstParameter = true;

                foreach (ParameterSymbol parameterSymbol in classSymbol.Constructor.Parameters)
                {
                    if (firstParameter == false)
                    {
                        writer.Write(", ");
                    }

                    TypeSymbol parameterType     = parameterSymbol.ValueType;
                    string     parameterTypeName = GetParameterTypeName(parameterType);
                    writer.Write(parameterTypeName);
                    firstParameter = false;
                }
            }

            writer.Write("], ");

            //base class
            if (classSymbol.BaseClass == null)
            {
                // TODO: We need to introduce the notion of a base class that only exists in the metadata
                //       and not at runtime. At that point this check of IsTestClass can be generalized.

                writer.Write("null");
            }
            else
            {
                writer.Write(classSymbol.BaseClass.FullGeneratedName);
            }

            //interfaces
            if (classSymbol.Interfaces != null)
            {
                writer.Write(", [");
                bool first = true;

                foreach (InterfaceSymbol inheritedInterface in classSymbol.Interfaces)
                {
                    if (!first)
                    {
                        writer.Write(", ");
                    }

                    string parameterTypeName = GetParameterTypeName(inheritedInterface);
                    writer.Write(parameterTypeName);
                    first = false;
                }

                writer.Write("]");
            }

            writer.Write(")");
        }
예제 #29
0
        private static void GenerateMethod(ScriptGenerator generator, string typeName, MethodSymbol methodSymbol)
        {
            if (methodSymbol.IsAbstract)
            {
                return;
            }

            ScriptTextWriter writer = generator.Writer;

            bool instanceMember = (methodSymbol.Visibility & MemberVisibility.Static) == 0;

            if (instanceMember == false)
            {
                writer.Write(typeName);
                writer.Write(".");
            }

            writer.Write(methodSymbol.GeneratedMemberName);

            if (instanceMember)
            {
                writer.Write(": ");
            }
            else
            {
                writer.Write(" = ");
            }

            bool hasParams = HasParamsModifier(methodSymbol);

            if (hasParams)
            {
                writer.Write($"{DSharpStringResources.ScriptExportMember("paramsGenerator")}(");
                writer.Write("{0}, ", methodSymbol.GetGeneratedParamsCount());
            }

            writer.Write("function(");
            WriteParameters(methodSymbol, writer, true);

            writer.WriteLine(") {");
            writer.Indent++;

            if (generator.Options.EnableDocComments)
            {
                DocCommentGenerator.GenerateComment(generator, methodSymbol);
            }

            CodeGenerator.GenerateScript(generator, methodSymbol);
            writer.Indent--;
            writer.Write("}");

            if (hasParams)
            {
                writer.Write(")");
            }

            if (instanceMember == false)
            {
                writer.WriteLine(";");
            }
        }
예제 #30
0
        private static void GenerateEvent(ScriptGenerator generator, string typeName, EventSymbol eventSymbol)
        {
            ScriptTextWriter writer = generator.Writer;

            ParameterSymbol valueParameter = eventSymbol.Parameters[0];

            string eventName = eventSymbol.GeneratedName;
            string fieldName = eventName;

            if (eventSymbol.DefaultImplementation)
            {
                fieldName = "__" + Utility.CreateCamelCaseName(eventSymbol.Name);

                Debug.Assert(eventSymbol.Parent.Type == SymbolType.Class);

                Symbol fieldSymbol = ((ClassSymbol)eventSymbol.Parent).GetMember(fieldName);
                Debug.Assert(fieldSymbol != null && fieldSymbol.Type == SymbolType.Field);

                fieldName = fieldSymbol.GeneratedName;
            }

            string fieldReference;

            if ((eventSymbol.Visibility & MemberVisibility.Static) == 0)
            {
                fieldReference = "this.";
            }
            else
            {
                fieldReference = typeName + ".";
            }

            fieldReference += fieldName;

            bool instanceMember = true;

            if ((eventSymbol.Visibility & MemberVisibility.Static) != 0)
            {
                instanceMember = false;
                writer.Write(typeName);
                writer.Write(".");
            }

            writer.Write("add_");
            writer.Write(eventName);

            if (instanceMember)
            {
                writer.Write(": ");
            }
            else
            {
                writer.Write(" = ");
            }

            writer.Write("function(");
            writer.Write(valueParameter.GeneratedName);
            writer.WriteLine(") {");
            writer.Indent++;

            if (generator.Options.EnableDocComments)
            {
                DocCommentGenerator.GenerateComment(generator, eventSymbol);
            }

            if (eventSymbol.DefaultImplementation)
            {
                writer.Write(fieldReference);
                writer.Write($" = {DSharpStringResources.ScriptExportMember("bindAdd")}(");
                writer.Write(fieldReference);
                writer.Write(", ");
                writer.Write(valueParameter.GeneratedName);
                writer.WriteLine(");");
            }
            else
            {
                CodeGenerator.GenerateScript(generator, eventSymbol, /* add */ true);
            }

            writer.Indent--;
            writer.Write("}");

            if (instanceMember == false)
            {
                writer.WriteLine(";");
            }

            if (instanceMember)
            {
                writer.WriteLine(",");
            }
            else
            {
                writer.Write(typeName);
                writer.Write(".");
            }

            writer.Write("remove_");
            writer.Write(eventName);

            if (instanceMember)
            {
                writer.Write(": ");
            }
            else
            {
                writer.Write(" = ");
            }

            writer.Write("function(");
            writer.Write(valueParameter.GeneratedName);
            writer.WriteLine(") {");
            writer.Indent++;

            if (generator.Options.EnableDocComments)
            {
                DocCommentGenerator.GenerateComment(generator, eventSymbol);
            }

            if (eventSymbol.DefaultImplementation)
            {
                writer.Write(fieldReference);
                writer.Write($" = {DSharpStringResources.ScriptExportMember("bindSub")}(");
                writer.Write(fieldReference);
                writer.Write(", ");
                writer.Write(valueParameter.GeneratedName);
                writer.WriteLine(");");
            }
            else
            {
                CodeGenerator.GenerateScript(generator, eventSymbol, /* add */ false);
            }

            writer.Indent--;
            writer.Write("}");

            if (instanceMember == false)
            {
                writer.WriteLine(";");
            }
        }