Пример #1
0
        public override void Translate(LambdaExpression model, TranslationContext context)
        {
            if (context.IsWritingGlobalStatements)
            {
                // write function declaration, with params
                context.Write("function(");
                context.WriteModels(model.Parameters, ", ");
                context.WriteLine(") {");

                // write inner body
                context.Indent();
                context.WriteModelBody(model.Body);
                context.Unindent();

                // close function declaration
                context.Write("}");
            }
            else
            {
                // write function declaration, with params
                context.Write("Blade.del(this, function(");
                context.WriteModels(model.Parameters, ", ");
                context.WriteLine(") {");

                // write inner body
                context.Indent();
                context.WriteModelBody(model.Body);
                context.Unindent();

                // close function declaration
                context.Write("})");
            }
        }
Пример #2
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("}");
        }
        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("}");
        }
Пример #4
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("};");
        }
Пример #5
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);
        }
Пример #6
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(";");
            }
        }
Пример #7
0
 public override void Translate(ThrowStatement model, TranslationContext context)
 {
     context.EnsureLineBreak();
     context.Write("throw ");
     context.WriteModel(model.Expression);
     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(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("}");
        }
Пример #10
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();
            }
        }
Пример #11
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(");");
        }
Пример #12
0
        public override void Translate(LocalDeclarationStatement model, TranslationContext context)
        {
            context.EnsureLineBreak();

            context.Write("var ");
            context.WriteModels(model.VariableDeclaration.Variables, ", " + Environment.NewLine);

            context.WriteLine(";");
        }
Пример #13
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("}");
        }
Пример #14
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("}");
        }
        public override void Translate(AnonymousMethodExpression model, TranslationContext context)
        {
            // write function declaration, with params
            context.Write("Blade.del(this, function(");
            context.WriteModels(model.Parameters, ", ");
            context.WriteLine(") {");

            // write inner body
            context.Indent();
            context.WriteModelBody(model.Body);
            context.Unindent();

            // close function declaration
            context.Write("})");
        }
Пример #16
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;
            }
        }
Пример #17
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("}");
            }
        }
Пример #18
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);
        }
Пример #19
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(";");
        }
Пример #20
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("};");
        }
Пример #21
0
 public override void Translate(ContinueStatement model, TranslationContext context)
 {
     context.EnsureLineBreak();
     context.WriteLine("continue;");
 }
Пример #22
0
        public override void Translate(ClassDeclaration model, TranslationContext context)
        {
            if (model == null)
            {
                return;
            }

            // make sure the namespace is available
            context.EnsureNamespace(model.Definition.Namespace);

            // begin the class closure
            context.WriteLine();
            context.WriteLine(model.Definition.GetFullName() + " = (function() {");
            context.Indent();

            if (model.IsDerived)
            {
                var baseName = model.Definition.BaseClass.GetFullName();

                // derive from base, and create a local variable to access base
                context.WriteLine(String.Format("Blade.derive({0}, {1});", model.Definition.Name, baseName));
                context.WriteLine("var $base = " + baseName + ".prototype;");
            }

            // write the class constructor
            var instanceCtors = model.Constructors.Where(c => !c.IsStatic);

            if (instanceCtors.Count() > 1)
            {
                throw new CompilationException("Constructor overloading is not supported.", model.Constructors[1]);
            }

            var ctor       = instanceCtors.FirstOrDefault() ?? new ConstructorDeclaration();
            var paramsText = String.Join(", ", ctor.Parameters.Select(p => p.Definition.Name));

            // write the ctor
            context.WriteLine(String.Format("function {0}({1}) {{", model.Definition.Name, paramsText));
            context.Indent();

            // write initialized fields, and return remaining fields
            // those remaining may safely be attached to the prototype
            var pFields = WriteCtorInitializers(model.Fields, context);

            if (model.IsDerived)
            {
                // write explicit call to base class ctor
                context.Write("$base.constructor.call(this");

                if (ctor.HasExplicitBaseCall)
                {
                    // check for arguments to the base ctor
                    var baseCtor = model.Definition.BaseClass.Constructors.FirstOrDefault();
                    if (baseCtor != null && baseCtor.Parameters.Any())
                    {
                        var baseArgs = TranslationHelper.GetInvocationArgs(baseCtor.Parameters, ctor.BaseArguments);
                        if (baseArgs.Any())
                        {
                            // write base ctor args
                            context.Write(", ");
                            context.WriteModels(baseArgs, ", ");
                        }
                    }
                }

                context.WriteLine(");");
            }

            context.WriteModelBody(ctor.Body);
            context.Unindent();
            context.WriteLine("}");

            // group all members
            var members = Enumerable.Empty <IMemberDeclarationModel>()
                          .Concat(pFields).Concat(model.Events)
                          .Concat(model.Properties).Concat(model.Methods);

            var instanceMembers = new List <IMemberDeclarationModel>();
            var staticMembers   = new List <IMemberDeclarationModel>();

            // separate instance and static members
            foreach (var item in members)
            {
                if (item.IsStatic)
                {
                    staticMembers.Add(item);
                }
                else
                {
                    instanceMembers.Add(item);
                }
            }

            // write instance members
            if (instanceMembers.Any())
            {
                context.PrepareForDeclarations(model.Definition.Name);
                context.EnsureLineBreak();

                foreach (var item in instanceMembers)
                {
                    context.WriteModel(item);
                }
            }

            // apply interfaces
            if (model.Definition.Interfaces.Any())
            {
                context.Write("Blade.impl(" + model.Definition.Name);

                foreach (var def in model.Definition.Interfaces)
                {
                    context.Write(", '" + def.GetFullName() + "'");
                }

                context.WriteLine(");");
            }

            // return class constructor and end closure
            context.EnsureLineBreak();
            context.WriteLine("return " + model.Definition.Name + ";");
            context.Unindent();
            context.WriteLine("})();");

            // write static members as global statements
            foreach (var item in staticMembers)
            {
                CompilationContext.Current.Model.GlobalStatements.Add(item);
                context.WriteModel(item);
            }

            // if the class has a static constructor, add to globals
            var staticCtor = model.Constructors.FirstOrDefault(c => c.IsStatic);

            if (staticCtor != null)
            {
                staticCtor.Body.HasBraces = false;
                CompilationContext.Current.Model.GlobalStatements.Add(staticCtor.Body);
            }
        }
Пример #23
0
        public override void Translate(TryStatement model, TranslationContext context)
        {
            // begin try
            context.EnsureLineBreak();
            context.WriteLine("try {");
            context.Indent();

            // write try body
            context.WriteModelBody(model.Body);

            // end try
            context.Unindent();
            context.EnsureLineBreak();
            context.Write("}");

            // write catches
            if (model.HasCatch)
            {
                foreach (var item in model.Catches)
                {
                    context.Write(" catch(");

                    // javascript catch requires an identifier, always
                    var identifier = (item.Identifier != null && !String.IsNullOrEmpty(item.Identifier.Name)) ? item.Identifier.Name : "ex$";
                    var typeName   = (item.Type != null && !String.IsNullOrEmpty(item.Type.GetFullName())) ? item.Type.GetFullName() : null;

                    context.Write(identifier);

                    if (typeName != null && typeName != "Error")
                    {
                        context.Write(" if " + identifier + " instanceof " + typeName);
                    }

                    // begin catch
                    context.WriteLine(") {");
                    context.Indent();

                    // write catch body
                    context.WriteModelBody(item.Body);

                    // end catch
                    context.Unindent();
                    context.EnsureLineBreak();
                    context.Write("}");
                }
            }

            if (model.HasFinally)
            {
                // begin finally
                context.WriteLine(" finally {");
                context.Indent();

                // write finally body
                context.WriteModelBody(model.FinallyBody);

                // end finally
                context.Unindent();
                context.EnsureLineBreak();
                context.Write("}");
            }

            context.WriteLine();
        }
Пример #24
0
        public override void Translate(PropertyDeclaration model, TranslationContext context)
        {
            if (model == null)
            {
                return;
            }

            string autoGetScript = null;
            string autoSetScript = null;

            if (model.IsAutoProperty)
            {
                // add a backing field
                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           = model.Definition.Type,
                        Kind           = DefinitionKind.Member,
                        MemberKind     = MemberDefinitionKind.Field
                    }
                };

                // 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";
                autoGetScript = "return " + fieldPrefix + "." + fieldName + ";";
                autoSetScript = fieldPrefix + "." + fieldName + " = value;";
            }

            // write the get accessor
            if (model.HasGetter || model.IsAutoProperty)
            {
                context.WriteDeclaration(model, "get_");
                context.WriteLine(" = function() {");
                context.Indent();

                if (model.IsAutoProperty)
                {
                    context.WriteLine(autoGetScript);
                }
                else
                {
                    context.WriteModelBody(model.GetAccessor);
                }

                context.Unindent();
                context.WriteLine("};");
            }

            // write the set accessor
            if (model.HasSetter || model.IsAutoProperty)
            {
                context.WriteDeclaration(model, "set_");
                context.WriteLine(" = function(value) {");
                context.Indent();

                if (model.IsAutoProperty)
                {
                    context.WriteLine(autoSetScript);
                }
                else
                {
                    context.WriteModelBody(model.SetAccessor);
                }

                context.Unindent();
                context.WriteLine("};");
            }
        }