Releases: polterguy/lizzie
Maintenance release fixing some crucial bugs
The previous release which contained support for dependency injection, unfortunately also had some pretty severe errors related to this feature. If you're using "deep binding" with Lizzie, you should update to this release ASAP. In this release Lizzie is using lambda expressions to bind to "unknown types", which will be used if you do a "deep binding" on your context. This implementation also allowed me to get rid of the dependencies on Reflection.Emit, which felt awkward anyway, resulting in a smaller and slicker code base, yet still perfectly supporting "deep binding". Invoking "deeply bound" functions now, should be at least 3 orders of magnitudes faster than in version 0.8.
Notice, read the section on optimizing Lizzie if you're experiencing performance issues related to reflection or the compilation of lambda expressions.
Dependency Injection support ++
Scientific notation of numbers
You can now use scientific notation to declare your numbers (thx to Robert McCausland). This allows you to for instance declare a number as the following 57.67e2
, which of course becomes the equivalent of 5767.0
. You can also use 5767e-2
, which becomes 57.67
. The syntax is similar to the normal syntax you'd use in e.g. C# etc to declare very large numbers, or very small numbers, using what's commonly referred to as "scientific notation".
Dependency Injection support
This version also allows you to bind your Lizzie code to a base class, and/or an interface, yet still allowing you to invoke Lizzie functions that are Bind
ed on your derived type(s). This allows you to (among other things) bind towards an instance of an interface, and still have access to Lizzie functions declared on your implementation type. Which (of course) is a pre-requisite for making Lizzie "Dependency Injection friendly".
Usage
class BaseClass
{
[Bind(Name = "foo1")]
protected object Foo1(Binder<BaseClass> ctx, Arguments arguments)
{
return 50;
}
}
class SuperClass : BaseClass
{
[Bind(Name = "foo2")]
object Foo2(Binder<BaseClass> ctx, Arguments arguments)
{
return 7;
}
}
/*
* Somewhere else in your code ...
*
* NOTICE!
* Type inference here will make sure your Binder uses "BaseClass" as
* its generic argument, yet still you're able to invoke methods on "SuperClass".
*/
BaseClass simple = new SuperClass();
/*
* The last "true" argument is important to "bind deeply" to your instance type!
* Without the "true", it will bind towards the inferred type, which for this example
* becomes "BaseClass".
*/
var lambda = LambdaCompiler.Compile(simple, "+(foo1(), foo2())", true);
var result = lambda();
/*
* result is now ==> 57
*/
Notice - Your Binder
is still type declared with its generic argument being your TContext
(base) type. And your base class must make its methods available to its derived classes, either as protected
, or somehow such that the method is available from your derived type(s). During creation of your Lizzie function(s) though, the calling hierarchy will be "flattened", giving you access to both static and instance methods, on both your super types, and your base types, as long as your most derived ("super") type somehow can legally invoke the method(s).
Thx to the following awesome coders ...
- Robert McCausland
- SapphireBrand
- Atifaziz
- Hoangitk
- Spadino
- Leslie Murphy
... for having helped me spot bugs, and sometimes contributed with merge requests and improvements.
It takes a village to create a Lizzie :)
Maintenance release
Fixed a pretty severe bug that made it impossible to de-reference the correct variable in functions. Now you can access and modify global variables, and/or you can declare your own function level scope variables that "hides" global variables with the same name. This makes Lizzie "almost functional". I considered making it entirely functional, but since this would make it much harder to change state, I realised that the way to look at a Lizzie piece of code, is as a method to an object, where the this object is your context, at which point making it functional would have been counter productive.
This is a pretty important release, and if you've had weird bugs de-referencing your variables with previous versions, hopefully this release fixes these problems.
JSON
The biggest change in this version is that Lizzie now has JSON support. This allows you to combine the newly created map
function that creates a Dictionary<string, object>
with the existing list
function that creates a List<object>
to both create and parse JSON.
To parse JSON, you can use the json
function, that will create a hierarchy of list
and map
items for you, depending upon the structure of your JSON. To create JSON, you can use the existing string
function to transform an existing hierarchy of list
and map
items into its JSON representation. In addition I have added a map
function, that allows you to create a Dictionary<string, object>
instance. A map
instance shares many of the same functions that list
had from before, such as get
, add
, etc. Hence these functions will now check to see if you're passing in a map or a list before figuring out what they should do. This reduces the number of unique keywords, at the additional cost of that you can't (easily) see what object types is being manipulated inside of functions. However, I am quite content with this solution myself.
Notice - For obvious reasons, I don't want to expand too much on Lizzie, since its main features is its lack of features. However, since being able to parse and create JSON is such an obvious and generic use-case, I felt these two additions could be justified. I am also using Newtonsoft's JSON library, but only for parsing JSON, although for Lizzie's usage of JSON, this library is probably extreme "overkill". At some point, I'll probably end up creating a smaller and slicker JSON parser, which should be possible with less than 50 lines of code, since the only types I need to map towards are map
and list
instances - So the features from Newtonsoft's JSON library becomes a complete overkill for Lizzie's needs, and creating something much smaller, avoiding the dependency altogether, is (probably) worth it.
Another nifty addition is the newly added apply
function, that allows you to take a list
, and apply its values as arguments to a function invocation. Probably the only thing missing in the "core language" at this point, is the ability to enumerate all arguments, such that you can have functions with variable arguments, not even having to name these arguments as you create your function. Whether or not I'll do this, depends upon some few things though, but it's on my TODO list, and the last remaining "core" feature in fact I'll do, before I consider the language to be 100% feature complete.
Implementing a functioning stack
Since the stack basically didn't work (at least not intuitively), I felt I had to create a new release, making a functioning stack available for my users.
The way the stack now works, is that everything you declare using var
at the global level becomes globally available for everything. Everything you declare inside a function using var
, will only be visible for that function, and disappear once the function is done evaluating. If you declare a variable inside a function, that has already been declared globally, your local variable declaration will "hide" the global variable locally within your function, but the global variable will be unaffected once your function is done evaluating. This is more or less the way the stack works in JavaScript, and should be intuitive to people used to JS.
Hopefully this should work according to the above description. There are some unit tests asserting this behaviour, and they're all green on my machine for sure :)
First real release
This is the first real release of Lizzie, a dynamic programming language for .Net. If you simply want to consume it, you can use the following command
PM > Install-Package lizzie
... or find it in NuGet using the graphical interface. If you need the source code for some reasons, you can download it from here.
Super duper alpha release
The header says it all