public override void Translate(AssignmentExpression model, TranslationContext context) { var origAssignee = context.CurrentAssignee; context.CurrentAssignee = model.Assignee; context.WriteModel(model.LeftExpression); context.CurrentAssignee = origAssignee; // handle special member kinds - property, and event var memberDef = model.Assignee.Definition as IMemberDefinition; if (memberDef != null) { switch (memberDef.MemberKind) { case MemberDefinitionKind.Property: HandlePropertyAssignment(model, context); return; case MemberDefinitionKind.Event: HandleEventAssignment(model, context); return; } } context.Write(" " + model.Operator + " "); context.WriteModel(model.RightExpression); }
public override void Translate(IsTypeExpression model, TranslationContext context) { context.Write("Blade.is("); context.WriteModel(model.LeftExpression); context.Write(", "); context.WriteModel(model.RightExpression); context.Write(")"); }
public override void Translate(ConditionalExpression model, TranslationContext context) { context.WriteModel(model.Condition); context.Write(" ? "); context.WriteModel(model.TrueExpression); context.Write(" : "); context.WriteModel(model.FalseExpression); }
private bool HandleSpecialCases(NewExpression model, TranslationContext context) { // check for special cases if (model.Type != null) { if (model.Type.TypeKind == TypeDefinitionKind.Delegate) { // delegates should have a single argument context.WriteModel(model.Arguments[0].Expression); return(true); } if (model.Type.TypeKind == TypeDefinitionKind.Anonymous) { // types view as anonymous, instanciate using object literal notation if (model.Initializer == null || !model.Initializer.Expressions.Any()) { context.Write("{}"); } else { context.WriteLine("{"); context.Indent(); for (int i = 0; i < model.Initializer.Expressions.Count; i++) { var assignment = model.Initializer.Expressions[i] as AssignmentExpression; if (assignment == null) { throw new CompilationException("All initializer expressions must be assignments.", model); } context.Write(assignment.Assignee.Definition.Name + ": "); context.WriteModel(assignment.RightExpression); if ((i + 1) < model.Initializer.Expressions.Count) { context.WriteLine(","); } } context.WriteLine(); context.Unindent(); context.Write("}"); } return(true); } } return(false); }
public override void Translate(AnonymousObjectExpression model, TranslationContext context) { context.WriteLine("{"); context.Indent(); var first = true; foreach (var item in model.Assignments) { if (first) { first = false; } else { context.WriteLine(","); } context.Write(item.Assignee.Definition.Name + ": "); context.WriteModel(item.RightExpression); // anonymous type members are created as properties // however, we translate the declaration as fields // thus must also change the member kind, so that // usage of the member is also translated correctly ((IMemberDefinition)item.Assignee.Definition).MemberKind = MemberDefinitionKind.Field; } context.EnsureLineBreak(); context.Unindent(); context.Write("}"); }
public override void Translate(MethodDeclaration model, TranslationContext context) { if (model == null) { return; } context.WriteDeclaration(model); context.Write(" = function ("); if (model.HasParameters) { context.WriteModels(model.Parameters, ", "); } // begin method context.WriteLine(") {"); context.Indent(); // set optional params to defaults foreach (var param in model.Parameters.Where(p => p.Definition.HasDefaultValue)) { context.Write(String.Format("{0} = ({0} !== undefined) ? {0} : ", param.Name)); context.WriteModel(param.DefaultExpression); context.WriteLine(";"); } // write method body context.WriteModelBody(model.Body); context.Unindent(); context.EnsureLineBreak(); context.WriteLine("};"); }
public override void Translate(ForStatement model, TranslationContext context) { context.EnsureLineBreak(); context.Write("for("); if (model.VariableDeclaration != null && model.VariableDeclaration.Variables.Any()) { context.Write("var "); context.WriteModels(model.VariableDeclaration.Variables, ", "); } else if (model.Initializers != null && model.Initializers.Any()) { context.WriteModels(model.Initializers, ", "); } // write condition context.Write("; "); context.WriteModel(model.Condition); // write incrementors context.Write("; "); context.WriteModels(model.Incrementors, ", "); // write body context.WriteLine(") {"); context.Indent(); context.WriteModelBody(model.Statement); context.Unindent(); context.WriteLine("}"); }
/// <summary> /// Executes the translation process. /// </summary> /// <param name="context">The compilation context.</param> public void Execute(CompilationContext context) { if (context == null || context.Model == null) return; if (context.OutputStream == null || !context.OutputStream.CanWrite) throw new CompilationException("The translation output stream is null or not writable."); var translationCtx = new TranslationContext(); translationCtx.OutputStream = context.OutputStream; // write enum declarations var enumTranslator = new EnumTranslator(); foreach (var item in context.Model.Enums) enumTranslator.Translate(item, translationCtx); // write class declarations var classTranslator = new ClassTranslator(); foreach (var item in ClassSorter.Sort(context.Model.Classes)) classTranslator.Translate(item, translationCtx); // write global statements if (context.Model.GlobalStatements.Any()) { translationCtx.WriteLine(); foreach (var item in context.Model.GlobalStatements) translationCtx.WriteModel(item); } }
public override void Translate(ThrowStatement model, TranslationContext context) { context.EnsureLineBreak(); context.Write("throw "); context.WriteModel(model.Expression); context.WriteLine(";"); }
public override void Translate(CastExpression model, TranslationContext context) { // currently there is no special behavior // applied when explicitly casting types. context.WriteModel(model.Expression); }
public override void Translate(ElementAccessExpression model, TranslationContext context) { context.WriteModel(model.Expression); context.Write("["); context.WriteModels(model.Arguments.Select(a => a.Expression), ", "); context.Write("]"); }
public override void Translate(MemberAccessExpression model, TranslationContext context) { if (HandleEnumMember(model, context) || HandleExtensionMethod(model, context)) { return; } var hasExpression = false; var hasMember = false; var length = context.Length; // write the member access expression context.WriteModel(model.Expression); if (context.Length > length) { // check if any text was actually written. hasExpression = true; length = context.Length; } // get a placeholder to the dot position var dotWriter = context.CreatePositionalWriter(); // account for making explicit base calls. if (model.Expression as BaseExpression != null) { context.UsingExplicitCall = true; } // write the member name context.WriteModel(model.Member); // check again if any text was written. if (context.Length > length) { hasMember = true; } // if the member access wrote text for both the // expression and member, add a dot between them if (hasExpression && hasMember) { dotWriter.Write("."); } }
public override void Translate(VariableDeclarator model, TranslationContext context) { context.Write(model.Definition.Name); if (model.EqualsValueExpression != null) { context.Write(" = "); context.WriteModel(model.EqualsValueExpression); } }
private void HandleEventAssignment(AssignmentExpression model, TranslationContext context) { // field => add_field(func, ctx); -or- rem_field(func, ctx); if (model.Operator == "+=") { context.Write("$add"); } else if (model.Operator == "-=") { context.Write("$rem"); } else { throw new CompilationException("Unexpected event operator of: " + model.Operator, model); } context.Write((context.UsingExplicitCall) ? ".call(this, " : "("); context.WriteModel(model.RightExpression); var rtMemberExp = model.RightExpression as MemberAccessExpression; if (rtMemberExp == null) { // events can also be assigned using new syntax // in which case we should use the inner expression var newExp = model.RightExpression as NewExpression; if (newExp != null && newExp.Arguments.Count == 1) { rtMemberExp = newExp.Arguments[0].Expression as MemberAccessExpression; } } if (rtMemberExp != null) { // set the event context context.Write(", "); context.WriteModel(rtMemberExp.Expression); } context.Write(")"); }
public override void Translate(NewExpression model, TranslationContext context) { if (HandleSpecialCases(model, context)) { return; } var hasInit = model.Initializer != null && model.Initializer.Expressions.Any(); if (hasInit) { // wrap in function context.Write("(function($0) { "); foreach (AssignmentExpression item in model.Initializer.Expressions) { // work around for Roslyn object initializers not supported if (item.Assignee.Definition is EmptyDefinition) { var typeDef = ((ContainerTypeDefinition)model.Type); if (typeDef != null) { var memberDef = typeDef.Properties.FirstOrDefault(p => p.Name == item.Assignee.Name) as IMemberDefinition ?? typeDef.Fields.FirstOrDefault(f => f.Name == item.Assignee.Name) as IMemberDefinition; if (memberDef != null) { item.Assignee.Definition = memberDef; item.LeftExpression = item.Assignee; } } } // end Roslyn object initializer workaround context.Write("$0."); context.WriteModel(item); context.Write("; "); } context.Write("return $0; })("); } // always create types by full name context.Write("new " + model.Type.GetFullName() + "("); if (model.HasArguments) { context.WriteModels(model.Arguments.Select(a => a.Expression), ", "); } context.Write(hasInit ? "))" : ")"); }
public override void Translate(InvocationExpression model, TranslationContext context) { context.WriteModel(model.Expression); var args = GetArguments(model); // when invoking explicitly, use 'call' and // explicity pass the 'this' context in if (context.UsingExplicitCall) { // use an explicit invocation call var hasArgs = args.Any() || context.ExtensionMethodTarget != null; context.Write(".call(this" + (hasArgs ? ", " : "")); // reset explicit call flag context.UsingExplicitCall = false; } else { context.Write("("); } // handle extension methods if (context.ExtensionMethodTarget != null) { // capture and set target to null, otherwise another // invocation expression will result in an infinite loop var target = context.ExtensionMethodTarget; context.ExtensionMethodTarget = null; context.WriteModel(target); if (args.Any()) { context.Write(", "); } } context.WriteModels(args, ", "); context.Write(")"); }
private void HandlePropertyAssignment(AssignmentExpression model, TranslationContext context) { context.Write((context.UsingExplicitCall) ? ".call(this, " : "("); if (model.Operator.Length > 1) { // complex assignment, such as +=, %=, etc. // create a new binary expression on the fly context.WriteModel(new BinaryExpression { LeftExpression = model.LeftExpression, RightExpression = model.RightExpression, Operator = model.Operator.Substring(0, 1) }); } else { context.WriteModel(model.RightExpression); } context.Write(")"); }
public override void Translate(ReturnStatement model, TranslationContext context) { context.EnsureLineBreak(); if (model.Expression == null) { context.WriteLine("return;"); } else { context.Write("return "); context.WriteModel(model.Expression); context.WriteLine(";"); } }
public override void Translate(SwitchStatement model, TranslationContext context) { // begin switch statement context.EnsureLineBreak(); context.Write("switch ("); context.WriteModel(model.Expression); context.WriteLine(") {"); context.Indent(); // write sections foreach (var section in model.Sections) { foreach (var label in section.Labels) { // labels context.EnsureLineBreak(); context.Write("case "); context.WriteModel(label); context.WriteLine(":"); } if (section.IsDefault) { context.WriteLine("default:"); } // write statements context.Indent(); context.WriteModels(section.Statements, ""); context.Unindent(); } // end statement context.Unindent(); context.WriteLine("}"); }
public override void Translate(WhileStatement model, TranslationContext context) { // begin while statement context.EnsureLineBreak(); context.Write("while ("); context.WriteModel(model.Condition); context.WriteLine(") {"); context.Indent(); // write inner statement context.WriteModelBody(model.Statement); // end while statement context.Unindent(); context.WriteLine("}"); }
private void WriteIfModel(IfStatement model, TranslationContext context, bool nested) { // if beginning of new statement, ensure line break if (!nested) { context.EnsureLineBreak(); } // opening if clause context.Write("if ("); context.WriteModel(model.Condition); context.WriteLine(") {"); // write statement context.Indent(); context.WriteModelBody(model.Statement); context.Unindent(); context.Write("}"); // write else condition, or newline if (model.HasElseStatement) { context.Write(" else "); // handle if-else explicitly var elseIf = model.ElseStatement as IfStatement; if (elseIf != null) { WriteIfModel(elseIf, context, true); } else { // begin final else statement context.WriteLine("{"); context.Indent(); // end final else statement context.WriteModelBody(model.ElseStatement); context.Unindent(); context.WriteLine("}"); } } else { context.WriteLine(); } }
public override void Translate(DoStatement model, TranslationContext context) { // begin do statement context.EnsureLineBreak(); context.WriteLine("do {"); context.Indent(); // write inner statement context.WriteModelBody(model.Statement); // end do statement // write while condition context.Unindent(); context.Write("} while ("); context.WriteModel(model.Condition); context.WriteLine(");"); }
/// <summary> /// Executes the translation process. /// </summary> /// <param name="context">The compilation context.</param> public void Execute(CompilationContext context) { if (context == null || context.Model == null) { return; } if (context.OutputStream == null || !context.OutputStream.CanWrite) { throw new CompilationException("The translation output stream is null or not writable."); } var translationCtx = new TranslationContext(); translationCtx.OutputStream = context.OutputStream; // write enum declarations var enumTranslator = new EnumTranslator(); foreach (var item in context.Model.Enums) { enumTranslator.Translate(item, translationCtx); } // write class declarations var classTranslator = new ClassTranslator(); foreach (var item in ClassSorter.Sort(context.Model.Classes)) { classTranslator.Translate(item, translationCtx); } // write global statements if (context.Model.GlobalStatements.Any()) { translationCtx.WriteLine(); translationCtx.IsWritingGlobalStatements = true; foreach (var item in context.Model.GlobalStatements) { translationCtx.WriteModel(item); } translationCtx.IsWritingGlobalStatements = false; } }
public override void Translate(ArrayCreationExpression model, TranslationContext context) { if (model.TypeExpression.RankExpressions.Count > 1) { throw new CompilationException("Multidimensional arrays are not supported.", model); } if (model.Initializer != null) { // write as initialized array. context.Write("["); context.WriteModels(model.Initializer.Expressions, ", "); context.Write("]"); } else { // write an new empty array (repecting default values) if (model.TypeExpression.RankExpressions.Count == 1) { var rankExp = model.TypeExpression.RankExpressions[0]; if (rankExp.Rank > 1) { throw new CompilationException("Multidimensional arrays are not supported.", model); } if (rankExp.Sizes.Any()) { context.Write("new Array("); context.WriteModel(rankExp.Sizes[0]); context.Write(")"); } else { context.Write("[]"); } } else { context.Write("[]"); } } }
public override void Translate(CodeBlock model, TranslationContext context) { if (model.HasBraces) { context.WriteLine("{"); context.Indent(); } foreach (var item in model.Statements) { context.WriteModel(item); } if (model.HasBraces) { context.EnsureLineBreak(); context.Unindent(); context.Write("}"); } }
// this writes field initializers that must be in the constructor // essentially this applies to any fields that are assigned mutable values private static IEnumerable <FieldDeclaration> WriteCtorInitializers(IEnumerable <FieldDeclaration> fields, TranslationContext context) { var outList = new List <FieldDeclaration>(); foreach (var f in fields) { if (f.Initializer != null && !f.IsStatic && !(f.Initializer is LiteralExpression)) { context.Write("this." + f.Name + " = "); context.WriteModel(f.Initializer); context.WriteLine(";"); } else { outList.Add(f); } } return(outList); }
public override void Translate(ForEachStatement model, TranslationContext context) { context.EnsureLineBreak(); var identifier = model.IdentifierName; var enumerator = "$" + identifier + "_enum"; context.WriteLine("var " + identifier + " = null;"); context.Write("var " + enumerator + " = "); context.WriteModel(model.Expression); context.WriteLine(".GetEnumerator();"); context.WriteLine("while(" + enumerator + ".MoveNext()) {"); context.Indent(); context.WriteLine(identifier + " = " + enumerator + ".get_Current();"); context.WriteModelBody(model.Statement); context.EnsureLineBreak(); context.Unindent(); context.WriteLine("}"); }
private bool HandleExtensionMethod(MemberAccessExpression model, TranslationContext context) { var symbol = model.Member.GetSymbolAs <IMethodSymbol>(); if (symbol == null) { return(false); } if (symbol.ReducedFrom == null) { return(false); } // reduced extension methods are viewed as instance members // we must explicitly set these to be static model.Member.Definition.Modifiers.IsStatic = true; // write the method itself, and set extension method context context.WriteModel(model.Member); context.ExtensionMethodTarget = model.Expression; return(true); }
public override void Translate(FieldDeclaration model, TranslationContext context) { if (model == null) { return; } context.WriteDeclaration(model); context.Write(" = "); if (model.Initializer == null) { context.Write(context.GetDefaultValue(model.Definition.Type)); } else { // write the initializer context.InitializingType = model.Container; context.WriteModel(model.Initializer); context.InitializingType = null; } context.WriteLine(";"); }
public override void Translate(EventDeclaration model, TranslationContext context) { if (model == null) { return; } string fieldAddScript = null; string fieldRemScript = null; if (model.IsField) { // add a backing event list var fieldName = "$" + model.Definition.Name; var backingField = new FieldDeclaration { Container = model.Container, OriginatingNode = model.OriginatingNode, OriginatingTree = model.OriginatingTree, Definition = new FieldDefinition { Name = fieldName, ContainingType = model.Definition.ContainingType, Type = new ClassDefinition() { Kind = DefinitionKind.Type, Name = "Event", Namespace = "Blade", } }, Initializer = new LiteralExpression { Type = LiteralType.None, Text = "new Blade.Event()" } }; // use same modifier as property, but force private backingField.Definition.Modifiers.Apply(model.Definition.Modifiers); backingField.Definition.Modifiers.Access = Accessibility.Private; context.WriteModel(backingField); // manually create get/set body var fieldPrefix = model.IsStatic ? model.Container.Name : "this"; var fieldAccess = fieldPrefix + "." + fieldName; fieldAddScript = fieldAccess + ".add(func, ctx);"; fieldRemScript = fieldAccess + ".rem(func);"; // add a method to invoke the event context.WriteDeclaration(model); context.WriteLine(" = function() {"); context.Indent(); context.WriteLine(fieldAccess + ".pub.apply(" + fieldAccess + ", arguments);"); context.Unindent(); context.WriteLine("}"); } // write the add accessor context.WriteDeclaration(model, postfix: "$add"); context.WriteLine(" = function(func, ctx) {"); context.Indent(); if (model.IsField) { context.WriteLine(fieldAddScript); } else { context.WriteModelBody(model.AddAccessor); } context.Unindent(); context.WriteLine("};"); // write the remove accessor context.WriteDeclaration(model, postfix: "$rem"); context.WriteLine(" = function(func) {"); context.Indent(); if (model.IsField) { context.WriteLine(fieldRemScript); } else { context.WriteModelBody(model.RemoveAccessor); } context.Unindent(); context.WriteLine("};"); }
public override void Translate(BinaryExpression model, TranslationContext context) { context.WriteModel(model.LeftExpression); context.Write(" " + ToJsOperator(model) + " "); context.WriteModel(model.RightExpression); }