コード例 #1
0
ファイル: Program.cs プロジェクト: modulexcite/IL2JS
 private static bool IsUpToDate(CompilerEnvironment env, CST.AssemblyDef assembly, bool complain)
 {
     var annot = assembly.Annotations.OfType<CST.AssemblyFileAnnotation>().FirstOrDefault();
     if (annot == null)
         throw new InvalidOperationException("assembly is missing file annotation");
     var fn = default(string);
     var lastCompTime = AssemblyCompiler.LastCompilationTime(env, assembly.Name, out fn);
     if (lastCompTime.HasValue)
     {
         if (annot.LastWriteTime <= lastCompTime.Value)
             return true;
         else
         {
             if (complain)
                 env.Log
                     (new OutOfDateAssemblyMessage(assembly.Name, annot.CanonicalFileName, fn));
             return false;
         }
     }
     else
     {
         if (complain)
             env.Log(new AssemblyNotCompiledMessage(assembly.Name, fn));
         return false;
     }
 }
コード例 #2
0
        // Collect types we need to compile
        private void CollectTypes()
        {
            foreach (var typeDef in assmEnv.Assembly.Types.Where(t => t.Invalid == null))
            {
                var tyconEnv = assmEnv.AddType(typeDef);
                if (typeDef.IsModule)
                {
                    // Look for any <Module>::.cctor()
                    // We know both <Module> and the .cctor have no type parameters
                    var methodDef =
                        typeDef.Members.OfType <CST.MethodDef>().Where
                            (m => m.Invalid == null && m.IsStatic && m.IsConstructor).FirstOrDefault();
                    if (methodDef != null)
                    {
                        moduleInitializer = methodDef.SelfMethodReference(tyconEnv);
                    }
                }

                if (typeDef.IsUsed)
                {
                    typeDefs.Add(typeDef);
                }
                else
                {
                    if (assemblyTrace == null || assemblyTrace.IncludeAssembly)
                    {
                        Env.Log(new UnusedDefinitionMessage(CST.MessageContextBuilders.Env(tyconEnv)));
                    }
                }
            }
        }
コード例 #3
0
        public void Add(string traceFileName, bool isInitial)
        {
            var name = Path.GetFileNameWithoutExtension(traceFileName);

            if (TraceMap.ContainsKey(name))
            {
                Env.Log(new InvalidTraceMessage(null, "duplicate trace names"));
                throw new ExitException();
            }
            var trace = new Trace(this, name, isInitial ? TraceFlavor.Initial : TraceFlavor.OnDemand);

            trace.Load(this, traceFileName);
            TraceMap.Add(name, trace);
        }
コード例 #4
0
 public void Emit()
 {
     if (Trace.Flavor == TraceFlavor.Remainder)
     {
         foreach (var kv in Trace.AssemblyMap)
         {
             var compiler = new AssemblyCompiler(this, kv.Value);
             compiler.Emit(null);
         }
     }
     else
     {
         var rootEnv = Env.Global.Environment();
         var body    = new Seq <JST.Statement>();
         body.Add(JST.Statement.Var(RootId, new JST.Identifier(Env.Root).ToE()));
         foreach (var nm in rootEnv.AllLoadedAssembliesInLoadOrder().Where(Trace.AssemblyMap.ContainsKey))
         {
             var compiler = new AssemblyCompiler(this, Trace.AssemblyMap[nm]);
             compiler.Emit(body);
         }
         var program = new JST.Program
                           (new JST.Statements
                               (new JST.ExpressionStatement
                                   (new JST.StatementsPseudoExpression(new JST.Statements(body), null))));
         var fileName = Path.Combine(Env.OutputDirectory, Trace.Name + ".js");
         program.ToFile(fileName, Env.PrettyPrint);
         Env.Log(new GeneratedJavaScriptFile("trace '" + Trace.Name + "'", fileName));
     }
 }
コード例 #5
0
        private static bool IsUpToDate(CompilerEnvironment env, CST.AssemblyDef assembly, bool complain)
        {
            var annot = assembly.Annotations.OfType <CST.AssemblyFileAnnotation>().FirstOrDefault();

            if (annot == null)
            {
                throw new InvalidOperationException("assembly is missing file annotation");
            }
            var fn           = default(string);
            var lastCompTime = AssemblyCompiler.LastCompilationTime(env, assembly.Name, out fn);

            if (lastCompTime.HasValue)
            {
                if (annot.LastWriteTime <= lastCompTime.Value)
                {
                    return(true);
                }
                else
                {
                    if (complain)
                    {
                        env.Log
                            (new OutOfDateAssemblyMessage(assembly.Name, annot.CanonicalFileName, fn));
                    }
                    return(false);
                }
            }
            else
            {
                if (complain)
                {
                    env.Log(new AssemblyNotCompiledMessage(assembly.Name, fn));
                }
                return(false);
            }
        }
コード例 #6
0
        public static int Main(string[] args)
        {
            var env = new CompilerEnvironment();

            try
            {
                // Collect command line args
                var cl = new CompilerCommandLine(env.Log, env);
                cl.MergeFromArgs(args);

                if (env.CompilationMode == CompilationMode.Traced && env.TraceFileNames.Count == 0 && string.IsNullOrEmpty(env.FinalTraceName))
                {
                    env.Log(new UsageMessage("'-mode traced' must be accompanied by at least on of '-trace' or '-finalTraceName' options."));
                    throw new ExitException();
                }

                env.SetupPrimTracer();

                // ----------------------------------------
                // Load the assemblies
                // ----------------------------------------

                // Renames
                var subst = new CST.AssemblyNameSubstitution(env.Log, env.PrimTracer, env.AssemblyNameResolution);
                foreach (var r in env.RenameRules)
                {
                    subst.Add(r);
                }

                // Augmentations
                var augmentations = new CST.AugmentationDatabase(subst);
                foreach (var fn in env.AugmentationFileNames)
                {
                    augmentations.AddFile(Path.Combine(env.InputDirectory, fn));
                }
                foreach (var sn in env.OriginalStrongNames)
                {
                    augmentations.AddOriginal(sn);
                }

                // Final references
                var loadedAssemblies = new CST.LoadedAssemblyDatabase(augmentations);
                foreach (var fileName in env.ReferenceFileNames)
                {
                    loadedAssemblies.Add(fileName, false);
                }
                foreach (var fileName in env.CompileFileNames)
                {
                    loadedAssemblies.Add(fileName, true);
                }

                var loader = new CST.PELoader(loadedAssemblies);
                var global = loader.Load();

                // Done with the loader
                loader = null;

                env.SetupMetadata(global);

                try
                {
                    env.Validity.Check();

                    foreach (var assmInfo in loadedAssemblies)
                    {
                        env.Log(new CST.LoadedAssemblyMessage(assmInfo.TargetAssemblyName));
                    }

                    if (env.Tracer != null)
                    {
                        env.Tracer.Trace
                            ("Loaded assemblies",
                            w =>
                        {
                            foreach (var assemblyDef in global.Assemblies)
                            {
                                assemblyDef.Append(w);
                                w.EndLine();
                            }
                        });
                    }

                    // ----------------------------------------
                    // Setup Interop
                    // ----------------------------------------
                    env.InteropManager.Setup();

                    // ----------------------------------------
                    // Collect assemblies
                    // ----------------------------------------

                    var allAssemblies        = new Set <CST.AssemblyDef>();
                    var compilingAssemblies  = new Set <CST.AssemblyDef>();
                    var referencedAssemblies = new Set <CST.AssemblyDef>();
                    var ok = true;
                    foreach (var assmInfo in loadedAssemblies)
                    {
                        var assembly = assmInfo.AssemblyDef;
                        allAssemblies.Add(assembly);
                        if (assmInfo.ForCompilation)
                        {
                            if (string.IsNullOrEmpty(env.OutputDirectory))
                            {
                                env.Log
                                    (new SkippingJavaScriptComplilation
                                        (assembly.Name, "No output directory was given"));
                                referencedAssemblies.Add(assembly);
                            }
                            else if (env.SkipUpToDate && IsUpToDate(env, assembly, false))
                            {
                                env.Log
                                    (new SkippingJavaScriptComplilation
                                        (assembly.Name, "Previously generated JavaScript is up to date"));
                                referencedAssemblies.Add(assembly);
                            }
                            else
                            {
                                compilingAssemblies.Add(assembly);
                            }
                        }
                        else
                        {
                            if (IsUpToDate(env, assembly, true))
                            {
                                referencedAssemblies.Add(assembly);
                            }
                            else
                            {
                                ok = false;
                            }
                        }
                    }

                    // Done with compilations
                    loadedAssemblies = null;

                    if (!ok)
                    {
                        throw new ExitException();
                    }

                    if (compilingAssemblies.Count > 0)
                    {
                        // ----------------------------------------
                        // Compile
                        // ----------------------------------------

                        switch (env.CompilationMode)
                        {
                        case CompilationMode.Plain:
                        case CompilationMode.Collecting:
                            // Compile all assemblies
                            foreach (var assemblyDef in compilingAssemblies)
                            {
                                var ac = new AssemblyCompiler(env, assemblyDef);
                                ac.Emit(null);
                            }
                            break;

                        case CompilationMode.Traced:
                            // Collect the trace file info
                            if (!string.IsNullOrEmpty(env.InitialTraceFileName))
                            {
                                env.Traces.Add(env.InitialTraceFileName, true);
                            }
                            foreach (var fn in env.TraceFileNames)
                            {
                                env.Traces.Add(fn, false);
                            }
                            env.Traces.AddFinalOrRemainder(env.FinalTraceName);
                            // Compile all traces and all remaining definitions
                            foreach (var kv in env.Traces.TraceMap)
                            {
                                var compiler = new TraceCompiler(env, kv.Value);
                                compiler.Emit();
                            }
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        // ----------------------------------------
                        // Runtime
                        // ----------------------------------------

                        if (env.Global.Assemblies.Any(a => a.EntryPoint != null))
                        {
                            // Emit the runtime itself
                            var compiler = new RuntimeCompiler(env);
                            compiler.Emit();
                        }
                    }
                }
                finally
                {
                    env.Teardown();
                }
            }
            catch (ExitException)
            {
                // No-op
            }
            catch (Exception e)
            {
                Console.WriteLine("Internal error: {0}", e.Message);
                Console.WriteLine("Please report this error to the developers");
                env.NumErrors++;
            }
            finally
            {
                Console.WriteLine("{0} errors, {1} warnings", env.NumErrors, env.NumWarnings);
            }
            return(env.NumErrors == 0 ? 0 : 1);
        }
コード例 #7
0
ファイル: Program.cs プロジェクト: modulexcite/IL2JS
        public static int Main(string[] args)
        {
            var env = new CompilerEnvironment();
            try
            {
                // Collect command line args
                var cl = new CompilerCommandLine(env.Log, env);
                cl.MergeFromArgs(args);

                if (env.CompilationMode == CompilationMode.Traced && env.TraceFileNames.Count == 0 && string.IsNullOrEmpty(env.FinalTraceName))
                {
                    env.Log(new UsageMessage("'-mode traced' must be accompanied by at least on of '-trace' or '-finalTraceName' options."));
                    throw new ExitException();
                }

                env.SetupPrimTracer();

                // ----------------------------------------
                // Load the assemblies
                // ----------------------------------------

                // Renames
                var subst = new CST.AssemblyNameSubstitution(env.Log, env.PrimTracer, env.AssemblyNameResolution);
                foreach (var r in env.RenameRules)
                    subst.Add(r);

                // Augmentations
                var augmentations = new CST.AugmentationDatabase(subst);
                foreach (var fn in env.AugmentationFileNames)
                    augmentations.AddFile(Path.Combine(env.InputDirectory, fn));
                foreach (var sn in env.OriginalStrongNames)
                    augmentations.AddOriginal(sn);

                // Final references
                var loadedAssemblies = new CST.LoadedAssemblyDatabase(augmentations);
                foreach (var fileName in env.ReferenceFileNames)
                    loadedAssemblies.Add(fileName, false);
                foreach (var fileName in env.CompileFileNames)
                    loadedAssemblies.Add(fileName, true);

                var loader = new CST.PELoader(loadedAssemblies);
                var global = loader.Load();

                // Done with the loader
                loader = null;

                env.SetupMetadata(global);

                try
                {
                    env.Validity.Check();

                    foreach (var assmInfo in loadedAssemblies)
                        env.Log(new CST.LoadedAssemblyMessage(assmInfo.TargetAssemblyName));

                    if (env.Tracer != null)
                        env.Tracer.Trace
                            ("Loaded assemblies",
                             w =>
                                 {
                                     foreach (var assemblyDef in global.Assemblies)
                                     {
                                         assemblyDef.Append(w);
                                         w.EndLine();
                                     }
                                 });

                    // ----------------------------------------
                    // Setup Interop
                    // ----------------------------------------
                    env.InteropManager.Setup();

                    // ----------------------------------------
                    // Collect assemblies
                    // ----------------------------------------

                    var allAssemblies = new Set<CST.AssemblyDef>();
                    var compilingAssemblies = new Set<CST.AssemblyDef>();
                    var referencedAssemblies = new Set<CST.AssemblyDef>();
                    var ok = true;
                    foreach (var assmInfo in loadedAssemblies)
                    {
                        var assembly = assmInfo.AssemblyDef;
                        allAssemblies.Add(assembly);
                        if (assmInfo.ForCompilation)
                        {
                            if (string.IsNullOrEmpty(env.OutputDirectory))
                            {
                                env.Log
                                    (new SkippingJavaScriptComplilation
                                         (assembly.Name, "No output directory was given"));
                                referencedAssemblies.Add(assembly);
                            }
                            else if (env.SkipUpToDate && IsUpToDate(env, assembly, false))
                            {
                                env.Log
                                    (new SkippingJavaScriptComplilation
                                         (assembly.Name, "Previously generated JavaScript is up to date"));
                                referencedAssemblies.Add(assembly);
                            }
                            else
                                compilingAssemblies.Add(assembly);
                        }
                        else
                        {
                            if (IsUpToDate(env, assembly, true))
                                referencedAssemblies.Add(assembly);
                            else
                                ok = false;
                        }
                    }

                    // Done with compilations
                    loadedAssemblies = null;                    

                    if (!ok)
                        throw new ExitException();

                    if (compilingAssemblies.Count > 0)
                    {
                        // ----------------------------------------
                        // Compile
                        // ----------------------------------------

                        switch (env.CompilationMode)
                        {
                        case CompilationMode.Plain:
                        case CompilationMode.Collecting:
                            // Compile all assemblies
                            foreach (var assemblyDef in compilingAssemblies)
                            {
                                var ac = new AssemblyCompiler(env, assemblyDef);
                                ac.Emit(null);
                            }
                            break;
                        case CompilationMode.Traced:
                            // Collect the trace file info
                            if (!string.IsNullOrEmpty(env.InitialTraceFileName))
                                env.Traces.Add(env.InitialTraceFileName, true);
                            foreach (var fn in env.TraceFileNames)
                                env.Traces.Add(fn, false);
                            env.Traces.AddFinalOrRemainder(env.FinalTraceName);
                            // Compile all traces and all remaining definitions
                            foreach (var kv in env.Traces.TraceMap)
                            {
                                var compiler = new TraceCompiler(env, kv.Value);
                                compiler.Emit();
                            }
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        // ----------------------------------------
                        // Runtime
                        // ----------------------------------------

                        if (env.Global.Assemblies.Any(a => a.EntryPoint != null))
                        {
                            // Emit the runtime itself
                            var compiler = new RuntimeCompiler(env);
                            compiler.Emit();
                        }
                    }
                }
                finally
                {
                    env.Teardown();
                }
            }
            catch (ExitException)
            {
                // No-op
            }
            catch (Exception e)
            {
                Console.WriteLine("Internal error: {0}", e.Message);
                Console.WriteLine("Please report this error to the developers");
                env.NumErrors++;
            }
            finally
            {
                Console.WriteLine("{0} errors, {1} warnings", env.NumErrors, env.NumWarnings);
            }
            return env.NumErrors == 0 ? 0 : 1;
        }
コード例 #8
0
        // Collect and filter members for subsequent code gen
        private void CollectMembers()
        {
            var fields     = new Seq <CST.FieldDef>();
            var events     = new Seq <CST.EventDef>();
            var properties = new Seq <CST.PropertyDef>();
            var methods    = new Seq <CST.MethodDef>();
            var exportedInstanceMethods = new Seq <CST.MethodDef>();

            StaticInitializer  = null;
            DefaultConstructor = null;
            numRelevantMethods = 0;

            foreach (var fieldDef in TyconEnv.Type.Members.OfType <CST.FieldDef>().Where(d => d.Invalid == null))
            {
                if (fieldDef.IsUsed)
                {
                    fields.Add(fieldDef);
                }
                else if (TypeTrace == null || TypeTrace.IncludeType)
                {
                    Env.Log
                        (new UnusedDefinitionMessage
                            (CST.MessageContextBuilders.Member
                                (Env.Global, TyconEnv.Assembly, TyconEnv.Type, fieldDef)));
                }
            }

            foreach (var eventDef in TyconEnv.Type.Members.OfType <CST.EventDef>().Where(d => d.Invalid == null))
            {
                if (eventDef.IsUsed)
                {
                    events.Add(eventDef);
                }
                else if (TypeTrace == null || TypeTrace.IncludeType)
                {
                    Env.Log
                        (new UnusedDefinitionMessage
                            (CST.MessageContextBuilders.Member
                                (Env.Global, TyconEnv.Assembly, TyconEnv.Type, eventDef)));
                }
            }

            foreach (var propDef in TyconEnv.Type.Members.OfType <CST.PropertyDef>().Where(d => d.Invalid == null))
            {
                if (propDef.IsUsed)
                {
                    properties.Add(propDef);
                }
                else if (TypeTrace == null || TypeTrace.IncludeType)
                {
                    Env.Log
                        (new UnusedDefinitionMessage
                            (CST.MessageContextBuilders.Member
                                (Env.Global, TyconEnv.Assembly, TyconEnv.Type, propDef)));
                }
            }

            var state = Env.InteropManager.GetTypeRepresentation(TyconEnv.Assembly, TyconEnv.Type).State;

            var s = TyconEnv.Type.Style;

            if (!(s is CST.InterfaceTypeStyle || s is CST.DelegateTypeStyle))
            {
                foreach (
                    var methodDef in
                    TyconEnv.Type.Members.OfType <CST.MethodDef>().Where(d => d.Invalid == null && !d.IsAbstract))
                {
                    if (!methodDef.IsUsed)
                    {
                        if (TypeTrace == null || TypeTrace.IncludeType)
                        {
                            Env.Log
                                (new UnusedDefinitionMessage
                                    (CST.MessageContextBuilders.Member
                                        (Env.Global, TyconEnv.Assembly, TyconEnv.Type, methodDef)));
                        }
                    }
                    else if (!Env.Validity.IsMustHaveADefinition(methodDef.QualifiedMemberName(Env.Global, TyconEnv.Assembly, TyconEnv.Type)) &&
                             (Env.InteropManager.IsInlinable(TyconEnv.Assembly, TyconEnv.Type, methodDef, state) ||
                              Env.InlinedMethods.IsInlinable(TyconEnv.Assembly, TyconEnv.Type, methodDef)))
                    {
                        if (TypeTrace == null || TypeTrace.IncludeType)
                        {
                            Env.Log
                                (new InlinedDefinitionMessage
                                    (CST.MessageContextBuilders.Member
                                        (Env.Global, TyconEnv.Assembly, TyconEnv.Type, methodDef)));
                        }
                    }
                    else if (state != InstanceState.JavaScriptOnly && state != InstanceState.ManagedAndJavaScript &&
                             !methodDef.IsStatic && methodDef.IsConstructor && methodDef.Arity > 1 &&
                             methodDef.ValueParameters[1].Equals(Env.JSContextRef))
                    {
                        // Silently ignore importing constructors unless they are needed.
                        // (Remember, the managed interop rewriter will interpert 'Merged' as
                        // 'JavaScriptOnly', and thus may need importing constructors.)
                    }
                    else
                    {
                        if (methodDef.IsStatic && methodDef.IsConstructor)
                        {
                            if (methodDef.TypeArity > 0)
                            {
                                throw new InvalidOperationException
                                          ("static constructors cannot be polymorphic");
                            }
                            StaticInitializer = new CST.MethodRef(TyconEnv.AddSelfTypeBoundArguments().TypeRef, methodDef.MethodSignature, null);
                        }
                        else if (!methodDef.IsStatic && methodDef.IsConstructor && methodDef.Arity == 1 &&
                                 !Env.InteropManager.IsFactory(TyconEnv.Assembly, TyconEnv.Type, methodDef))
                        {
                            if (methodDef.TypeArity > 0)
                            {
                                throw new InvalidOperationException
                                          ("instance constructors cannot be polymorphic");
                            }
                            DefaultConstructor = new CST.MethodRef(TyconEnv.AddSelfTypeBoundArguments().TypeRef, methodDef.MethodSignature, null);
                        }
                        if (Env.InteropManager.IsExported(TyconEnv.Assembly, TyconEnv.Type, methodDef))
                        {
                            if (Env.InteropManager.IsBindToInstance
                                    (TyconEnv.Assembly, TyconEnv.Type, methodDef))
                            {
                                exportedInstanceMethods.Add(methodDef);
                            }
                            // else: will be exported by assembly's Initialize function
                        }

                        methods.Add(methodDef);

                        if (TypeTrace == null || TypeTrace.Methods.Contains(methodDef.MethodSignature))
                        {
                            numRelevantMethods++;
                        }
                    }
                }
            }
            // else: ignore members of interface and delegate types
            // TODO: Need to emit reflection data for methods of interface types, thus will need
            //       to collect interface methods

            Fields     = fields;
            Events     = events;
            Properties = properties;
            Methods    = methods;
            ExportedInstanceMethods = exportedInstanceMethods;
        }
コード例 #9
0
        public void Emit()
        {
            var assm    = typeof(RuntimeCompiler).Assembly;
            var res     = "Microsoft.LiveLabs.JavaScript.IL2JS." + Constants.RuntimeFileName;
            var runtime = default(JST.Program);

            using (var runtimeStream = assm.GetManifestResourceStream(res))
            {
                if (runtimeStream == null)
                {
                    throw new InvalidOperationException("unable to find runtime resource");
                }
                runtime = JST.Program.FromStream(Constants.RuntimeFileName, runtimeStream, true);
            }

            var mode = default(string);

            switch (env.CompilationMode)
            {
            case CompilationMode.Plain:
                mode = "plain";
                break;

            case CompilationMode.Collecting:
                mode = "collecting";
                break;

            case CompilationMode.Traced:
                mode = "traced";
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            var body = default(ISeq <JST.Statement>);

            if (env.DebugMode)
            {
                body = new Seq <JST.Statement>();
                body.Add
                    (JST.Statement.Var(Constants.DebugLevel, new JST.NumericLiteral(env.DebugLevel)));
                body.Add(JST.Statement.Var(Constants.DebugId, new JST.BooleanLiteral(true)));
                body.Add(JST.Statement.Var(Constants.ModeId, new JST.StringLiteral(mode)));
                body.Add(JST.Statement.Var(Constants.SafeId, new JST.BooleanLiteral(env.SafeInterop)));
                foreach (var s in runtime.Body.Body)
                {
                    body.Add(s);
                }
            }
            else
            {
                // Simplify
                var simpCtxt =
                    new JST.SimplifierContext(true, env.DebugMode, new JST.NameSupply(Constants.Globals), null).
                    InFreshStatements();
                simpCtxt.Bind(Constants.DebugId, new JST.BooleanLiteral(false));
                simpCtxt.Bind(Constants.ModeId, new JST.StringLiteral(mode));
                simpCtxt.Bind(Constants.SafeId, new JST.BooleanLiteral(env.SafeInterop));
                simpCtxt.Add(JST.Statement.Var(Constants.DebugLevel, new JST.NumericLiteral(env.DebugLevel)));
                runtime.Body.Simplify(simpCtxt, EvalTimes.Bottom, false);
                body = simpCtxt.Statements;
            }

            var opts         = new OrdMap <JST.Identifier, JST.Expression>();
            var mscorlibName = new JST.StringLiteral
                                   (CST.CSTWriter.WithAppend(env.Global, CST.WriterStyle.Uniform, env.Global.MsCorLibName.Append));

            opts.Add(Constants.SetupMscorlib, mscorlibName);
            var target = default(string);

            switch (env.Target)
            {
            case Target.Browser:
                target = "browser";
                break;

            case Target.CScript:
                target = "cscript";
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
            opts.Add(Constants.SetupTarget, new JST.StringLiteral(target));
            var loadPaths = env.LoadPaths.Select <string, JST.Expression>(FixupPath).ToSeq();

            if (loadPaths.Count == 0)
            {
                loadPaths.Add(new JST.StringLiteral(""));
            }
            opts.Add(Constants.SetupSearchPaths, new JST.ArrayLiteral(loadPaths));

            if (env.DebugMode)
            {
                body.Add(new JST.CommentStatement("Setup runtime"));
            }
            var rootId = new JST.Identifier(env.Root);

            body.Add(JST.Statement.Var(rootId, new JST.ObjectLiteral()));
            body.Add(JST.Statement.Call(Constants.NewRuntime.ToE(), rootId.ToE(), new JST.ObjectLiteral(opts)));

            var program         = new JST.Program(new JST.Statements(body));
            var runtimeFileName = Path.Combine(env.OutputDirectory, Constants.RuntimeFileName);

            program.ToFile(runtimeFileName, env.PrettyPrint);
            env.Log(new GeneratedJavaScriptFile("runtime", runtimeFileName));
        }