Monday, July 6, 2009

Taking a break.

Well,

After giving it some thought, I've decided that for a little while, I need a break. So I'm going to focus on other endeavors for the mean time and post here again once that changes.

Sunday, June 14, 2009

Language Integrated Query - Manual or Aided Objectified Building

Well,

Today's project was implementing an objectified representation of Language Integrated Query. Even before I started, I knew that I wanted it to be as seamless as the original, so I decided to create two variants of the structure: your standard AST form, and a 'builder' form. Where the builder takes responsibility for selecting the proper body type (select, group, select into, group into), initializing the expression, including the clauses in the order you specify them, and then finally building the expression.

Here's an example of both versions, I used an example from the C# Programming guide (How to: Perform Left Outer Joins) because I needed a simple example for demonstrative purposes.

First up is the method to build the expressions through the normal do it yourself method:

ILinqExpression queryTestA = new LinqExpression();
queryTestA.From = new LinqFromClause(/* rangeVariableName: */"person", /* rangeSource: */"people".GetSymbolExpression());
var queryTestABody = new LinqSelectBody();
queryTestA.Body = queryTestABody;
queryTestABody.Clauses.Join(/* rangeVariableName: */"pet",    /* rangeSource: */"pets".GetSymbolExpression(), /* conditionLeft: */"person".GetSymbolExpression(), /* conditionRight: */"pet".Fuse("Owner"), /* intoRangeName: */"gj");
queryTestABody.Clauses.From(/* rangeVariableName: */"subPet", /* rangeSource: */"gj".Fuse("DefaultIfEmpty").Fuse(new IExpression[0]));
queryTestABody.Selection = "string".Fuse("Format").Fuse("{0,-15}{1}".ToPrimitive(), "person".Fuse("FirstName"), ((Symbol)"subPet").EqualTo(IntermediateGateway.NullValue).IIf("string".Fuse("Empty"), "subPet".Fuse("Name")));


Next is the seamless version using the aid:
ILinqExpression queryTestB = LinqHelper
                             .From(/* rangeVariableName: */"person", /* rangeSource: */(Symbol)"people")
                             .Join(/* rangeVariableName: */   "pet", /* rangeSource: */(Symbol)"pets", /* conditionLeft: */(Symbol)"person", /* conditionRight: */"pet".Fuse("Owner"), /* intoRangeName: */"gj")
                             .From(/* rangeVariableName: */"subPet", /* rangeSource: */"gj".Fuse("DefaultIfEmpty").Fuse(new IExpression[0]))
                             .Select(/* selection: */"string".Fuse("Format").Fuse("{0,-15}{1}".ToPrimitive(), "person".Fuse("FirstName"), ((Symbol)"subPet").EqualTo(IntermediateGateway.NullValue).IIf("string".Fuse("Empty"), "subPet".Fuse("Name")))).Build();


So far it seems to pretty well emphasize the difference. Earlier today the selection line was horrendous due to constructing binary operations, I hadn't yet created extensions for simplifying their construction. Ensuring the operands are affixed to the proper precedence created very nasty looking code. I didn't use the original example's anonymous type initialization because I simply haven't created the ground work for it yet, so that's probably next on my list.

Here's an output to the console on printing the string version of the expression (defaults to C# syntax in the ToString overrides, for this programmer's convenience):
from person in people
join pet in pets on person equals pet.Owner into gj
from subPet in gj.DefaultIfEmpty()
select string.Format("{0,-15}{1}", person.FirstName, subPet == null ? string.Empty : subPet.Name)


And in doing so I noticed one thing, I have to be careful about examples, I used a 'string' instead of 'String' as a symbol. While C# might understand that when emitting, and VB's nicety of being case-insensitive will to, other language's that don't support it, won't.

Friday, May 22, 2009

Lambda Expressions - Hoisting

Just musing over the concept of lambda expressions, AKA. anonymous methods. If what I understand is correct, the entire method of hoisting involves a simple analysis of the scopes involved within the hoist. You'd merely have to create a scope dependency chain within each scope. If a scope depends on another scope, you evaluate the associated variables, and move them forward. This process would be nested, and if a sub-scope depended upon a scope two levels higher, the parent scope would also depend upon its parent's scope, albeit indirectly. The scopes, in essence would reference one another as instances of the classes that represent each individual scope.

I'll post more once I've got a working implementation within the code generation framework.

Building a framework for compilers...

I'm taking a break from the Parser Compiler madness to work on some functionality that would be useful for a compiler. It's what I call an AssemblyWorkspace. It's basically a large scale wrapper around the concept of an INamespaceParent (which is also a type parent). In creating an AssemblyWorkspace, you provide it with the assembly that's its 'core' assembly. Typical examples would be the Intermediate Project you're working on building through the infrastructure. On top of the core assembly, there's the referenced assemblies.

The namespace of the workspace is a union of all the namespaces within its scope, same goes for the types. When a type is encountered, if there are multiple instances of that type in the current scope, a light-weight wrapper type is introduced into the system, an ambiguity type. The ambiguity type contains a list of the types that are locked for the name.

Now the concept is simple, but making it work is a lot of work. I'm making it as simple and straight forward as any other INamespaceParent, so you can iterate the namespace names, types, and so on without having to worry about where that type comes from. Its aim is to simplify the symbol resolution phase. It'll be used for the global scope that exists beyond the current type hierarchy the code structure has available to it. I'll likely create a scope system which will use an AssemblyWorkspace as its core aspect and go from there. The other fun issue with it is making it malleable so that when references are inserted and removed, the workspace remains current. The final issue is speed. The higher level the implementation the more likely it is to be slow. The Abstraction Project is very high level. Its meant to be as simple as can be and every concept that can be expressed in a simplified form, is.

Common example:

var myAssembly = IntermediateGateway.CreateAssembly("myAssembly");
myAssembly.AssemblyInformation.AssemblyVersion = new Version(1, 0);
var defaultNamespace = myAssembly.Namespaces.Add("MyNamespace.Subnamespace");
var testClass = defaultNamespace.Classes.Add("TestClass");
var bitwiseAndOp = testClass.BinaryOperatorCoercions.Add(CoercibleBinaryOperators.BitwiseAnd, testClass);


The scope implementation will have an alias system, an import system (for namespaces) and general querying functionality to simplify lookup.

On an amusing note, I create some hellateous type-names:
IntermediateGenericSegmentableInstantiableType<IClassCtorMember,IIntermediateClassCtorMember,IClassEventMember,IIntermediateClassEventMember,IntermediateClassEventMember.EventMethodMember,IClassFieldMember,IIntermediateClassFieldMember,IClassIndexerMember,IIntermediateClassIndexerMember,IClassMethodMember,IIntermediateClassMethodMember,IClassPropertyMember,IIntermediateClassPropertyMember,IClassType,IIntermediateClassType,IntermediateClassType>.BinaryOperatorMember