Dalke Scientific Software: More science. Less time. Products
[ previous | newer ]     /home/writings/diary/archive/2007/06/01/lolpython

LOLPython

Combining the cuteness of LOLCODE and the cuddliness of Python I bring you....

LOLPython

LOLPython!

Download lolpython.py

WHATZ LOLPython?

Example code to generate all Fibonacci numbers less than a given value of N. Max value is 100 if N is not given on the command line. Idea derives from original lolcode implementation by Kieran O'Niell.

IN MAI datetime GIMME date LIKE DATE

SO IM LIKE FIBBING WIT N OK?
    LOL ITERATE FIBONACCI TERMS LESS THAN N /LOL
    SO GOOD N BIG LIKE EASTERBUNNY
    BTW, FIBONACCI LIKE BUNNIES! LOL
    U BORROW CHEEZBURGER
    U BORROW CHEEZBURGER
    I CAN HAZ CHEEZBURGER
    HE CAN HAZ CHEEZBURGER
    WHILE I CUTE?
        I AND HE CAN HAZ HE AND I ALONG WITH HE
        IZ HE BIG LIKE N?
            KTHXBYE
        U BORROW HE

IZ __name__ KINDA LIKE "__main__"?
    COMPLAIN "NOW IZ" AND DATE OWN today THING
    IZ BIGNESS ARGZ OK KINDA LIKE 1?
        N CAN HAS 100
    NOPE?
        N CAN HAS NUMBR ARGZ LOOK AT 1!!
    GIMME EACH I IN UR FIBBING WIT N OK?
        VISIBLE I
and in action (you must first install the most excellent PLY package):
% python lolpython.py fib.lol 60
NOW IZ 2007-06-01
1
1
2
3
5
8
13
21
34
55
It works by coverting the LOLPython code into Python. The converted Fibonacci in Python is:
# LOLPython to Python converter version 1.0
# Written by Andrew Dalke, who should have been working on better things.

# sys is used for COMPLAIN and ARGZ
import sys as _lol_sys

from datetime import date as DATE 

def FIBBING ( N ) :
    'ITERATE FIBONACCI TERMS LESS THAN N' 
    assert N >= 0 
    # BTW, FIBONACCI LIKE BUNNIES! LOL
    yield 1 
    yield 1 
    I = 1 
    HE = 1 
    while 1:
        I , HE = HE , I + HE 
        if HE >= N :
            break 
        yield HE 

if __name__ == '__main__' :
    print >>_lol_sys.stderr, 'NOW IZ' , DATE . today ()
    if len(_lol_sys.argv) == 1 :
        N = 100 
    else :
        N = int(_lol_sys.argv[ 1 ]) 
    for I in FIBBING ( N ) :
        print I 

# The end.
Like all modern software should, LOLPython has unit tests.
% python lolpython.py loltests.lol
UNIT TESTS R LEET!
READYSETGO!!!
...........
----------------------------------------------------------------------
Ran 11 tests in 0.001s

OK

Import, classes, iterators, generators, exceptions, comparison, operators .. most of Python is supported by LOLPython. Not everything, so free free to add the rest. It's in the public domain so you can do whatever you want. Just don't complain if/when it doesn't work. I am a consultant so if you want to pay me to maintain it, let me know :) .

Using LOLPython on the command line

Run a program from stdin

% echo "VISIBLE 'HAI WORLD!'" | python lolpython.py
HAI WORLD!
%

Translate a program from stdin into Python on stdout

% echo "COMPLAIN 'HAI WORLD!'" | python lolpython.py --convert
# LOLPython to Python converter version 1.0
# Written by Andrew Dalke, who should have been working on better things.


# sys is used for COMPLAIN and ARGZ
import sys as _lol_sys

print >>_lol_sys.stderr, 'HAI WORLD!' 

# The end.

Specify the LOLPython program filename on the command line

% cat count_letters.lol
LETTERZ CAN HAS INVISIBLE BUCKET
F CAN HAS open WIT "count_letters.lol"!
S CAN HAS F OWN read THING
GIMME EACH C IN THE S?
    N CAN HAS LETTERZ OWN get WIT C AND 0! ALONG WITH CHEEZBURGER
    LETTERZ LET THE C OK CAN HAS N
GIMME EACH C IN THE sorted WIT LETTERZ OK?
    VISIBLE repr WIT C! AND LETTERZ LOOK AT C!
% python lolpython.py count_letters.lol | head
'\n' 8
' ' 67
'!' 4
'"' 2
'.' 1
'0' 1
'?' 2
'A' 16
'B' 4
'C' 15

Translate one or more LOLPython program files into Python files

% python lolpython.py --convert count_letters.lol
% cat count_letters.py 
# LOLPython to Python converter version 1.0
# Written by Andrew Dalke, who should have been working on better things.


# sys is used for COMPLAIN and ARGZ
import sys as _lol_sys

LETTERZ = {}
F = open ( 'count_letters.lol' ) 
S = F . read ()
for C in S :
    N = LETTERZ . get ( C , 0 ) + 1 
    LETTERZ [ C ] = N 
for C in sorted ( LETTERZ ) :
    print repr ( C ) , LETTERZ [ C ] 

# The end.

Implementation

I started with the GardenSnake parser I wrote last year, because it could handle Python's indentation grammar. Pulled out the parser component so there's only a lexer. The converter is quite simple. It reads the LOLPython tokens and converts each one to Python code. The only hard part is that "!" or "OK" act as close ")", "}" or "]" to match whichever was the most recent opening form.

Indeed, you could say that LOLPython is a Python macro. But then the Lisp people might get mad at me.

I take it back. The hard part was figuring out the LOLPython grammar so it would be reasonably cute and cover most of Python.

Future

Ha! Ha-ha-ha-ha! I've had enough with this project. But if you want to make changes, go ahead. Some thoughts: improved error reporting, preserve original indentation, finish support for all of Python, add an import hook for ".lol" files, add missing unit tests, improve the grammar, fix predecence bugs (like "AINT GOOD" -> "assert not" where the "not" doesn't have the right strength), and write a converter from Python to LOLPython.


Andrew Dalke is an independent consultant focusing on software development for computational chemistry and biology. Need contract programming, help, or training? Contact me



Copyright © 2001-2013 Andrew Dalke Scientific AB