Plastic Language take 2


This is a follow-up on my earlier posts regarding my toy language plastic:
http://rogeralsing.com/2010/04/14/playing-with-plastic/
http://rogeralsing.com/2010/04/17/more-on-plastic/

After some brain storming with my colleague Sebastian Markbåge, we’ve come up with some alternative approaches to chained method calls.

Instead of chaining calls syntactically, I could instead chain them by passing the result of the last statement into the next function invocation, somewhat like pipelining in F# but without any syntactic interference.

 Lets take the “if / else” scenario which I have used before.

In my first attempt in plastic, the syntax would be:

if (condition)
{
   ...body...
}
else
{
   ...body...
}; // <- terminate the if / else chain with ";"

This worked fine, but it came with the drawback that I had to terminate every chain with “;”, even a single if statement.. if (…) {…};
It was also up to the “if” function to decide if the “else” function would be called.

With the new approach, the “if” function would execute like normal, and if the condition was not met, it would return the value/symbol “fail”.
The “else” function would be a special function that requires a “last value” as its first argument, this way, the evaluator “knows” that the last evaluated result should be applied to the “else” function.

Like this:

if (condition) //if condition fails, return "fail"
{
   ...body...
}
else //the last evaluated value and the else body is applied to the else function.
{
   ...body...
} // <- don't need any terminator, all {..} blocks always terminate a statement

This way, the else function would have two arguments, the last result and a closure representing it’s body.

The else function would be implemented like this:

func else (lastresult,body)
{
  let result = lastresult;

  if (last == fail) // if the last function returned fail, then execute the else body
     result = body(); //invoke the body and assign to result

    result;
}

This means that I can make a language wich is syntactically very similar to JavaScript (for whatever that is worth) and at the same time support invocation chains of functions/macros.
So this is more powerful than the earlier attempt and with a nicer syntax due to the skipped requirement of terminating chains with “;”

Ideas?

More on Plastic


I’ve added some more features to my toy language “Plastic”.

Partial application of function arguments.
This is now used for generators.
Yield is no longer a core function, instead, each generator takes a closure as its last argument which is then supplied by the foreach function.
This way the foreach body don’t have to be stored as a symbol, it is just passed as an argument to the generator.

func Range(low,high,yield)
{
    for(let i=low,i<=high,i++)
    {
        yield(i);
    };
};

// apply value to "low"
let From10 = Range(10);

// apply value to "high"
foreach(x in From10(20))
{ //this block is transformed to a closure and passed to yield
    print(x);
};

Break and Continue
Loop behavior can now be altered with break and continue.
I implemented those as special values that breaks any execution flow almost like exceptions.
The values are then bubbled up to the first loop which consumes the values and perform the appropriate action.

I guess exceptions and “return” could be implemented the same way.

[Edit]

I’ve added some basic one way coroutine support to support breaking out of generators that are constructed from nested loops.
Before, a break would only exit the most inner loop of the generator.

Now I can do things like this:

func primes(low,high,yield)
{    
    foreach(i in range(low,high))   
    {             
         foreach(j in range(2,i/2))        
         { 
             if (i % j == 0)
             {
                break;
             };
         }
         else
         {  
             yield(i);
         };         
    }; 
};


foreach(prime in primes(2,100))
{
    print(prime);
    if (prime > 50,break);
}
else
{
    print(""done"");
};

Plastic – Added generator support


I’ve added generator support to my toy language “Plastic”.
It’s quite funny how easy it is to implement some language features once you understand how they work behind the scenes.
At first, I thought generators would be extremely hard to implement, requiring AST transformations to build state machines a’la C# for enumerable methods.

But my java script guru colleague Sebastian Markbåge stated “its simple, just invoke the for each body as a closure from the generator when you hit yield”.
It’s so brilliant, no AST transformations and I could implement the whole thing in less than 20 LOC.

This enables me to write code like this:

//a generator function
func Range(low,high)
{
    for(let i=low,i<=high,i++)
    {
        yield(i); 
    };
};

//loop over the generator values
foreach(x in Range(5,20))
{
    foreach(y in Range(1,2))
    {
        print ("yielded " + x + " " +y);
    };
};

Looks like a real language almost, doesn’t it? :-)

So what going on here?

Well, the foreach function creates a closure of its own body with a single in argument, this closure is then stored and the generator function is invoked.
Once the generator calls the “yield” function, the yield function will route the yielded value into the closure of the foreach body.
This works fine even for nested loops.

Playing with Plastic


As some of you might know, I’ve been fiddling with a generic DSL grammar, here and here.

I figured that I should do some proof of concept on this and started to write a language using the grammar and parser.
Since I’ve already created a LISP clone earlier, I thought I should go with something similair, but using my C like grammar.
The evaluator is beeing developed using F#, a wonderful language for this kinds of things, forget any bashing I’ve done on F# ;-)

The results of my experiments is a language that is somewhat similair to JavaScript, but with LISP’ish macro support.
I lie if I say it’s real macros, but I can get similair results as LISP macros.

How it works:

The C# based parser parses the source code and returns a generic AST.
I then use F# to translate the generic AST into a similair F# based AST, just to make it easier to consume it from F#
The F# AST is then passed to my F# evaluator, which simply traverses the AST and evaluates the branches in the AST.

F# does an amazing job here, the AST evaluator is only around 150 LOC and some 100 LOC for the core functions, like “if” and “func”.

With these 250 lines of code, I get features like:

Macro like functions:

func for(ref init,ref cond,ref step,ref body)
{
    init();
    let result = null;
    while(cond())
    {
        result = body();
        step();
    };
    result;
};

//makes it possible to do:
for(let i=0,i<3,i++)
{
    print(i);
};

Chained expressions:

The macro like support allows me to add new constructs to the language, unlike other languages
like Boo or Ruby where you can pass closures as the last argument to a function, I can pass an entire chain of functions or expressions as the tail argument.
thus allowing constructs like:

if(x)
{
}
elif(y)
{
}
else
{
};

Note that “;” terminates a chain, which is the reason why there is a “;” at the end of a “for” block for example.
This is the reason I picked the somewhat corny name “Plastic” for the language, because it can be molded to support new consturcts.

Passing functions:

//passing functions
func f(x)
{
    x + 3;
};

func g(function,x)
{
    function(x) * function(x);
};

print (g(f,7));

Returning functions(closures):

func makefun()
{
    let x = 10;
    func()
    {
        x++;
        print(x);
    };
};

let fun = makefun();
fun();
fun();
fun();

There is still lots of things I want to add, e.g. There is no OO support at all right now, nor is there any way to deal with simple things like arrays.
So there is more to come.