示例#1
0
        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(")");
 }
示例#3
0
 public override void Translate(ConditionalExpression model, TranslationContext context)
 {
     context.WriteModel(model.Condition);
     context.Write(" ? ");
     context.WriteModel(model.TrueExpression);
     context.Write(" : ");
     context.WriteModel(model.FalseExpression);
 }
示例#4
0
        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("}");
        }
示例#6
0
        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("};");
        }
示例#7
0
        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("}");
        }
示例#8
0
        /// <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);
            }
        }
示例#9
0
 public override void Translate(ThrowStatement model, TranslationContext context)
 {
     context.EnsureLineBreak();
     context.Write("throw ");
     context.WriteModel(model.Expression);
     context.WriteLine(";");
 }
示例#10
0
        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);
            }
        }
示例#14
0
        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(")");
        }
示例#15
0
        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 ? "))" : ")");
        }
示例#16
0
        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(")");
        }
示例#17
0
        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(")");
        }
示例#18
0
        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(";");
            }
        }
示例#19
0
        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("}");
        }
示例#20
0
        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("}");
        }
示例#21
0
        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();
            }
        }
示例#22
0
        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(");");
        }
示例#23
0
        /// <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("[]");
                }
            }
        }
示例#25
0
        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("}");
            }
        }
示例#26
0
        // 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);
        }
示例#27
0
        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);
        }
示例#29
0
        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(";");
        }
示例#30
0
        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("};");
        }
示例#31
0
 public override void Translate(BinaryExpression model, TranslationContext context)
 {
     context.WriteModel(model.LeftExpression);
     context.Write(" " + ToJsOperator(model) + " ");
     context.WriteModel(model.RightExpression);
 }