[.net] Parsing expressions made up of any .NET object

This topic is 3366 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

I have built an assembler that has a primitive (and buggy) arrangement to parse expressions. It supports two types internally (strings and doubles) and each label the user creates can be one or the other. Each operator checks both operands and performs what it deems to be the most sensible operation on them. I need to rewrite the way that labels and expressions are handled due to the aforementioned bugs, and was pondering whether it would be practical to support all .NET types, and what the easiest way to handle that would be. Internally each label value could be an object, but how exactly would one add two objects together and get a meaningful result? It doesn't appear to be possible to invoke operators via reflection. PowerShell manages it somehow ($x = 123;$y = 456; [console]::writeline($x+$y)), and it would of course be possible to check for the standard primitive types and handle those yourself manually, but that seems rather clunky.

Share on other sites
Operators are a pain in the neck to deal with in a generic way. I've got a few good links bookmarked on the subject that I'll point you to, but I'm not sure how well they'll help your situation.

Generic Operators
Using generics for calculations

Share on other sites
Quote:
 Original post by benryvesIt doesn't appear to be possible to invoke operators via reflection.

You're right that it's not possible to invoke operators on primitive types via reflection, as those are handled directly by MSIL instructions.

However, it is possible to invoke overloaded operators via reflection, as they are nothing more than methods handled specially by the compiler. To find them via reflection, they have names like "op_Addition" and "op_Multiply". Additionally, they will have the IsSpecialName property set to true to distinguish them from normal methods.

So yes, you will have to end up special casing the primitive types. This should be pretty easy to do by having simple helper methods that do nothing more than add/multiply/etc two ints/doubles/what-have-you. To make it easier to detect primitive types, you can use the IsPrimitive property of your operand's type object.

Share on other sites
Indeed. For the non-primatives, there will be a static function on the first param's type (iirc) that defines the operator. Primatives will need to be hard-coded or redirected to a mostly hard-coded intermediary.

For Tangent, I created the mostly hard-coded intermediaries and the plus operator acts as a global method group. The 'best candidate' picking works on the standard behavior of the language off of that.

Share on other sites
Thanks for the replies. I'd seen complaints and suggested workarounds for people attempting to constrain generic types on operators before, so I wasn't too hopeful. I was more concerned about doing it the manual way only to find out that it was in fact possible to do it in a more elegant solution. Cheers!

Share on other sites
This isn't anything I've tried, but in theory, if you aren't targeting the compact framework, at the point when you try foo @ bar, you can create a function:
object magic(FooType a, BarType b) {  return a @ b;}

and run it through the compiler at runtime. If the compiler accepts the function, then load the function into a map and keep it around if you ever need that kind of magic again. There are probably still some corner cases involving primitives that would need to be resolved, but it should be a bit less work than trying to code everything manually.

Share on other sites
That may well work, something else to try. [smile] Thanks for the ideas!

Share on other sites
Looks like .NET 3.5 makes this nice and easy.

static object Add(object a, object b) {	var Parameters = new[] {		Expression.Parameter(a.GetType(), "a"),		Expression.Parameter(b.GetType(), "b"),	};	var Adder = Expression.Lambda(Expression.Add(Parameters[0], Parameters[1]), Parameters).Compile();	return Adder.DynamicInvoke(a, b);}

That appears to be able to add any two objects you feed it, provided the two have some sort of addition defined. Primitive types work fine, as do types with overloaded operators. Nifty!

Share on other sites

This topic is 3366 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Create an account

Register a new account

• Forum Statistics

• Total Topics
628667
• Total Posts
2984143

• 13
• 10
• 10
• 9
• 9