Leaf

Leaf: Preserving “lvalue” status

I’ve been reworking how I handle basic type conversion in Leaf. This is a mechanism which allows implicit conversion of simple types. As part of this effort I had to refactor how lvalues work. In brief, an lvalue is simply a value which can be modified by assignment.

I realized that I could now solve an annoying issue of imperative programming. How often do you encounter code that looks like the following?

if( cond )
	a = some_expr;
else
	b = some_expr;

I’ve always hated that repetition of not just ‘some_expr’ but the assignment as well. In leaf I allow lvalues to survive conditionals. A working example:

var a : integer;
var b : integer;
(true then b else a) = 17;
trace(b);

Note: you probably won’t need the parens since ‘=’ has a low enough precedence. I’ve just put them there for clarity. Of course you’d have an actual condition rather than just ‘true’.

This works for any conditional statement, though the only other one I have implemented so far is a switch (switches can return values). Its syntax isn’t so pretty yet (I haven’t settled on a good one), but here’s an example.

var a : integer;
var b : integer;
var c : integer;
switch {
	cond_a then a,
	cond_b then b,
	else c
} = 17;

C++

In C++ the same thing works using a ternary operator. If both operand types are lvalues then the resulting type is also an lvalue. It doesn’t work in C as-is, but with pointers and some syntax changes you can achieve something similar.

//C++ only
int a, b;
(1 ? a : b) = 17;

//C as well
*(1 ? &a : &b) = 17;

Categories: Leaf

Tagged as: , ,

4 replies »

    • I want to unify the ternary and if-else constructs, so it makes the syntax more difficult. That is, an if-else is merely a ternary which selects between code blocks. This is the part where I’m struggling to find a good unifying syntax.

  1. Your switch statement that returns an lvalue looks like a lambda that returns a reference to variables:

        int a, b, c;
        int condition = 2;
        auto s_ret = [&]() -> int &
        {
            switch (condition)
            {
                case 1: return a;
                case 2: return b;
                default: return c;
            }
        };
        s_ret() = 32;
    

    I don’t know if you know what a switch-case structure really is. It’s essentially a jump table. In your case it seems to be a subroutine that returns an lvalue. You seem to implement the switch as an if-else-if… lambda:

        int a, b, c;
        bool condition_a, condition_b;
        auto s_ret = [&]() -> int &
        {
            if (condition_a)
                return a;
            else if (condition_b)
                returb b;
            else
                return c;
        };
        s_ret() = 32;
    

    I think the (boolean_condition ? a : b) = c;
    structure is good enough, hey you can even nest them:

        (bol1 ? (bol2 ? a : b) : c) = d;
    

    But you want to avoid function overhead as it seems, since you avoid calling a function like I do (with the lambda):

        int &ref = (bol1 ? a : b);
        ref = 3;
    

    Then again, you don’t really need the int &ref reference but it’s just to demonstrate the principle.

    • My switches allow full expression conditions on each case, rather than a single value match (those will also come, I just haven’t done them yet). I agree the ?: is okay for a ternary case, but I don’t find it expands well to the general case. It may not be possible, but I’m hoping I can have a single conditional syntax which is essentially the same for if-else, and switch, whether used as flow control or value selection. Obviously my current syntax is not the desired goal. :(

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