Skip to main content

Posts

Showing posts with the label code generation

Sasa.Func - Type-Safe Delegate Combinators

This is the third post in my series of posts on useful Sasa abstractions: Sasa.Parsing - type-safe, extensible lexing and parsing framework Sasa.Dynamics - type-safe polytypic/reflective programming This post will deal with a the Sasa.Func static class in the stand-alone core Sasa assembly. This core assembly is concerned mainly with addressing limitations in the core .NET base class libraries. For instance, it contains type-safe, null-safe and thread-safe event operations , extensions on IEnumerable, useful extensions to numbers, and so on. Sasa.Func is particularly concerned with providing type-safe extensions on delegates. You can view the whole API online . Sasa.Func is available in the core Sasa.dll. Sasa.Func.Id The simplest starting point is Sasa.Func.Id . Use this method whenever you need a delegate that simply returns its argument. This is fairly common when using the System.Linq API. Usage: int[][] nested = new int[][] { { 0, 1, 2 }, { 3, 4, 5 }, { 6,...

Managed Data for .NET

Ensō is an interesting new language being developed by Alex Loh, William R. Cook, and Tijs van der Storm. The overarching goal is to significantly raise the level of abstraction, partly via declarative data models. They recently published a paper on this subject for Onwards! 2012 titled Managed Data: Modular Strategies for Data Abstraction . Instead of programmers defining concrete classes, managed data requires the programmer to define a schema describing his data model, consisting of a description of the set of fields and field types. Actual implementations of this schema are provided by "data managers", which interpret the schema and add custom behaviour. This is conceptually similar to aspect-oriented programming, but with a safer, more principled foundation. A data manager can implement any sort of field-like behaviour. The paper describes a few basic variants: BasicRecord: implements a simple record with getters and setters. LockableRecord: implements locking on...

CLR: Verification for Runtime Code Generation

The CLR's lightweight code generation via DynamicMethod is pretty useful, but it's sometimes difficult to debug the generated code and ensure that it verifies. In order to verify generated code, you must save the dynamic assembly to disk and run the peverify.exe tool on it, but DynamicMethod does not have any means to do so. In order to save the assembly, there's a more laborious process of creating dynamic assemblies, modules and types, and then finally adding a method to said type. This is further complicated by the fact that a MethodBuilder and DynamicMethod don't share any common interfaces or base types for generating IL, despite both of them supporting a GetILGenerator() method . This difficulty in switching between saved codegen and pure runtime codegen led me to add a CodeGen class to Sasa, which can generate code for either case based on a bool parameter. Since no common interface is available for code generation, it also accepts a delegate to which it dispa...

Embedded Stack Language for .NET - Redux

Awhile ago, I had posted about an embedding of a stack language in C#. The type signatures of the functions and the stack object encoded the consumption and production of stack values, so if your program compiled, it ran correctly. Unfortunately, the prior structure had a safety problem when generating code which I noted, but didn't have time to address. The new structure provided below does not have the safety problem, and any functions that compile are guaranteed to execute correctly. I have also altered the style to emphasize the row variable representing the "rest of the record" which the operation knows nothing about. The row variable is denoted by "_". This is still a fairly limited embedding, but I have added a few convenience functions, and may yet add more. Here is a sample program: var d = new DynamicMethod("test", typeof(void), null); var s = 1.Load() // load constant: { int } .Int(2) // load constan...

Embedded Stack Language for .NET

Parametric polymorphism is a powerful tool for constructing and composing safe programs. To demonstrate this, I've constructed a tiny embedded stack language in C#, and I exploited C# generics, aka parametric polymorphism, to ensure that any embedded programs are type-safe, and thus, "can't go wrong". Moreover, this language is jitted, since I use ILGenerator of System.Reflection.Emit, and the complexity of doing this was no higher than creating an interpreter. This is mainly because the CLR is itself a stack-based VM, and so jitting a stack-based program to a stack-based IL is fairly natural. Here is the type-safe representation of the stack: public struct Stack<R, T> : IDisposable { internal ILGenerator gen; public Stack(ILGenerator gen) { this.gen = gen; } public void Dispose() { this.Return(); } } This type encapsulates the IL output stream and uses two phantom type variables to encode the values at the top of the ...