tags:

views:

199

answers:

7

I remember when .NET 4 was in beta there was a video of a developer that made a command-line app that he could type C# code into and it would compile the code on the fly. The idea was that the compiler was now available in the .NET language.

Anyone recall where this is? I need to create an application with a small macro language and I would love to use C# as that macro language, but I don't know where to find this library..

+1  A: 

Not sure where the one you're referring to is anymore, but what you're talking about is an Interactive Shell.

The only one I recall seeing is the CSharpRepl which was released by the Mono team. CSharpRepl also contains the Compiler As a Service functionality that the Mono team developed.

Justin Niessner
+8  A: 

You can use the CSharpCodeProvider class to compile assemblies at runtime.

You'll need to make a boilerplate template to wrap the macro commands in a static method in a class.

For example:

static readonly Assembly[] References = new[] { typeof(Enumerable).Assembly, typeof(Component).Assembly };
public Action CompileMacro(string source) {
    var options = new CompilerParameters(References.Select(a => a.Location).ToArray()) {
        GenerateInMemory = true
    };
    string fullSource = @"public static class MacroHolder { public static void Execute() { \r\n" + source + "\r\n} }";
    try {
        var compiler = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });

        var results = compiler.CompileAssemblyFromSource(options, fullSource);

        if (results.Errors.Count > 0)
            throw new InvalidOperationException(String.Join(
                Environment.NewLine, 
                results.Errors.Cast<CompilerError>().Select(ce => ce.ErrorText)
            ));

        return (Action)Delegate.CreateDelegate(
            typeof(Action),
            results.CompiledAssembly.GetType("MacroHolder").GetMethod("Execute")
        );
    } finally { options.TempFiles.Delete(); }
}
SLaks
This is the only answer available now. The video you're referring to is demonstrating the "compiler as a service", which is tentatively planned for C# 5.
Stephen Cleary
See also: http://stackoverflow.com/questions/2210734/what-is-the-state-of-the-c-compiler-as-a-service
Stephen Cleary
Nice, thanks for the help everyone!
Kelly
A: 

Maybe you mean CodePad.NET? Well, it's not a command-line app but it is open-source and might point you in the right direction.

Ben Voigt
+1  A: 

You can try CS-Script as an alternative - allows you to run individual C# files as if they were script files.

Kynth
+1  A: 

If you're open to other suggestions, you can use Python or F# or Boo as a macro language today.

I prefer Python, myself; it's one of the best-designed languages. C# has borrowed heavily from Python in its later developments (iterator blocks, lambdas, ...).

Manning Publications has a book called IronPython in Action; chapter 15 is all about using IronPython in other programs (as a scripting engine, or as plugins).

Stephen Cleary
A: 

I wouldn't go Python, it doesn't have the .NET infrastructure, therefore you are limited.

F# is amazing.

Turing Complete
What do you mean by "doesn't have the .NET infrastructure"? IronPython is a first-class .NET language.
nikie
A: 

The Compiler-as-a-Service feature has been available in Mono for quite some time and there are signs that it might appear in .NET 5 or 6, but it's not available in .NET 4.

If you absolutely, positively, need to run on .NET (note that Mono runs on Windows just fine, so you don't actually lose anything by running Mono), one interesting option might be to investigate how hard it would be to port Mono.CSharp to .NET. I mean, ultimately, at some point, it generates CIL bytecode which works exactly the same across all CLI implementations whether that be Mono, .NET, DotGNU, Rotor, Bartok or whatever.

Otherwise, your options are pretty much the same they have always been: generate files and call the commandline compier, use DLR trees, use lightweight code generation, use Reflection.Emit, use CodeDOM, use CSharpCodeProvider, create your own scripting language, host some other scripting language or host the DLR.

I'd probably go for the latter: hosting the DLR is absolutely easy and it gives you access to not only one but several good scripting languages (at the moment Ruby, Python, ECMAScript and Scheme) and in fact the user can use any DLR language they have installed on their machine.

Jörg W Mittag