A Dev Story: Invariants

Todays’ post is about a small hobby of mine of looking into the details of creating a fully featured dev environment, more precisely I’m going to talk about how to start designing your own scripting language. This series will revolve around C++ because of reasons, but if anyone should request it I can easily port it to any compatible language

Anyway hype words aside let’s say you want to start creating your own scripting language. The first thing that comes to mind is storing data.

Now like everybody knows, the whole idea behind a scripting language is to be able to forget about the burdens of having to use cryptic language features, or wasting time on the planning required for writing programs in statically typed languages, so it only feels natural that our scripting language will feature dynamic typing. In other words if I have a variable a and I do
a = 'b';
a = 10;
a +=100;
print(a)

It should work as expected and not complain about anything.

Well back in the real world we have two solutions for this, either use another language that already has this feature (but of course that would most likely have little to no sense) which leaves having to build this thing in a boilerplate code friendly environment.

So first of all we want to create a base on which to build this system. We don’t want to expose too much information here, just the bare minimum to get a context in case it’s needed. This is achieved via a class that will have a member variable to describe what it holds

class InvUnknown{
public:
 virtual bool inline is(int type){return inv_type == type;}
 virtual int inline getType(){return inv_type;}
protected:
 InvUnknown(int type){inv_type = type;}
private:
 int inv_type;
}; 

Now like we specified earlier, we want our invariant to be able to hold any type of data we might encounter in the script, ideally it would have to do this without grabbing every last bit of memory it can get its hands on and without having to force the construction of another invariant when we want to set the value, which is why we’ll be using unions.

 union Data{
 double doubleData;
 int integerData;
 float floatData;
 string *stringData;
 InvUnknown *invariantData;
};

We’d like to somehow limit the amount of datatypes we put into this union though because having a plethora of datatypes + data storage combinations would eventually become cumbersome, so we’ll have the union store only simple primitives and objects and if the need arrives to hold an array for instance we will just use an invariant.

And now that the base is set we define the invariant as such:

template <typenameT,intType>
class Invariant:public InvUnknown
{
public:
 Invariant():InvUnknown(Type){}
 Invariant(T&_data):InvUnknown(Type), data(_data){}
 virtual T inline getData(){return data;}
 virtual const string toString(){
 stringstream buffer;
 string retval;
 buffer << &data;
 buffer >> retval;
 return retval;
};
protected:
 T data;
}; 

And this is it, now all there is to do is to define the set of methods that can be applied given any type T you want to support and then particularize the invariant by deriving it like so:

class Primitive:public Invariant<Data,PRIMITIVE>{
};

Next time we’ll talk about applying the same principle to functions

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s