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(); }
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(")"); }
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(";"); }
private static void GeneratePropertyComment(ScriptTextWriter writer, PropertySymbol propertySymbol) { GenerateSummaryComment(writer, propertySymbol); writer.Write("/// <value"); GenerateTypeAttributes(writer, propertySymbol.AssociatedType); writer.WriteLine("></value>"); }
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++; } } }
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(); }
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(); }
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>"); }
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(); }
private static void GenerateReturnsComment(ScriptTextWriter writer, TypeSymbol typeSymbol) { if (IsVoid(typeSymbol)) { return; } writer.Write("/// <returns"); GenerateTypeAttributes(writer, typeSymbol); writer.WriteLine("></returns>"); }
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(); } }
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(")"); }
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(); } }
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("}"); }
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("]"); }
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(); } } }
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(");"); } }
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;"); } }
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(");"); } }
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\""); } } }
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(")"); } }
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(); } }
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("}"); }
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("}"); } }
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; } } }
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($"));"); } }
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(", "); }
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(")"); }
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(";"); } }
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(";"); } }