5
\$\begingroup\$

Recently Torbjörn Söderstedt shipped the chicken programing specification. The basic premise of chicken is this: Only the word chicken, spaces and line breaks may be used. It was inspired by this paper and this talk.

Along with the specification he also created a javascript function that implements the chicken VM. Sadly (or joyfully?) he wrote the function with little more than the word chicken and thus mad if very very hard to understand.

I was wondering, could anyone do a code review of chicken.js? Maybe add a bunch of in-line comments?

function chicken(CHICKEN, Chicken) {
    Chicken &&( chicken. chicken =[,
    CHICKEN, CHICKEN = Chicken = chicken.
    $Chicken =-( CHICKEN ==( chicken.
    Chicken = Chicken ))], chicken.
    chicken [Chicken++] = chicken. chicken, chicken.
    CHICKEN = ++Chicken, chicken (--Chicken), chicken.
    $Chicken = ++Chicken, chicken. CHICKEN++ );
    Chicken = chicken. Chicken [chicken.
    $Chicken++ ]; chicken. Chicken = CHICKEN? Chicken?
    '\012'== Chicken? chicken (++ CHICKEN, chicken.
    chicken [++ chicken. CHICKEN ]=
    CHICKEN - CHICKEN ): Chicken
    ==' '|'\015'== Chicken ||
    (Chicken   )== "c" &  chicken. Chicken [chicken.
    $Chicken++ ]== "h" &  chicken. Chicken [chicken.
    $Chicken++ ]== "i" &  chicken. Chicken [chicken.
    $Chicken++ ]== "c" &  chicken. Chicken [chicken.
    $Chicken++ ]== "k" &  chicken. Chicken [chicken.
    $Chicken++ ]== "e" &  chicken. Chicken [chicken.
    $Chicken++ ]== "n"&&++chicken. chicken [chicken.
    CHICKEN]? chicken (CHICKEN)
    :[ "Error on line "+CHICKEN+": expected 'chicken'",
       chicken. CHICKEN = CHICKEN ++- CHICKEN ]:
    chicken. chicken :( CHICKEN = chicken.
    Chicken[chicken.CHICKEN], Chicken? (Chicken =

    --Chicken? --Chicken? --Chicken? --Chicken? --Chicken?
    --Chicken? --Chicken? --Chicken? --Chicken?
    chicken. CHICKEN++ &&
    --Chicken :'&#'+CHICKEN+';': chicken.
    Chicken [chicken. Chicken [-- chicken. CHICKEN ]&&
    (chicken. $Chicken += CHICKEN), --chicken.
    CHICKEN ]: chicken. Chicken [chicken.
    Chicken [CHICKEN] = chicken. Chicken
    [-- chicken. CHICKEN ],-- chicken. CHICKEN ]:
    chicken. Chicken [chicken. Chicken [chicken.
    $Chicken++ ]] [CHICKEN]: CHICKEN == chicken.
    Chicken [-- chicken. CHICKEN ]:
    CHICKEN*chicken. Chicken [-- chicken.
    CHICKEN ]: chicken. Chicken [-- chicken.
    CHICKEN ]- CHICKEN: chicken. Chicken [-- chicken.
    CHICKEN ]+ CHICKEN: chicken.
    CHICKEN ++ && "chicken", chicken.
    Chicken [chicken. CHICKEN ]= Chicken, chicken
    ()): CHICKEN );

    return chicken.
    Chicken
}
\$\endgroup\$
  • 6
    \$\begingroup\$ This question appears to be off-topic because it isn't actually asking for code review and also you didn't write the code. \$\endgroup\$ – svick Jul 1 '13 at 23:45
  • \$\begingroup\$ Well. I did ask for a code review, but that might be the wrong language. What I'm really hoping for is an explanation of what is going on in this odd bit of javascript. At first I figured this was a goodish question for stackoverflow, but they decided not and purposed it would do better here (which it has). SO Question -> stackoverflow.com/questions/17414435/… \$\endgroup\$ – mcwhittemore Jul 2 '13 at 1:03
6
\$\begingroup\$

Here's my first analysis. It's not complete, but the VM should be mostly understandable now. I've included some testcases from the homepage in the bottom.

var out,
    stack,
    input_ptr,
    stack_ptr;

function chicken(c, b)
{
    if(b)
    {
        // run once at the beginning of each interpretation
        // after this, chicken is only called recursively with one argument

        if(c == b)
        {
            out = b;
            c = b = input_ptr = 0;
            stack = [undefined, c, 0]
            stack[0] = stack;
            stack_ptr = 2;
            // parse the code
            chicken(1);
            // parsing is done, run the code
            input_ptr = 2;
            stack_ptr++;
        }
        else
        {
            // code is equal to input?!
            stack = [undefined, c, c = b = input_ptr = -( c == (out = b))];
            stack[b++] = stack;
            stack_ptr = ++b;
            chicken(--b);
            input_ptr = ++b;
            stack_ptr++;
        }
    }

    // either one character from the code
    // or a number of chickens to be interpreted as code
    b = out[input_ptr++];

    if(c)
    {
        // parsing
        if(b)
        {
            if(b == '\n')
            {
                // start counting on the top of the stack
                stack[++stack_ptr] = 0;
                return out = chicken(c + 1, 0);
            }
            else
            {
                // call chicken again, if:
                // 1. input it ' ' or '\r'
                // 2. input is 'chicken'
                // In the latter case, increment the top of the stack
                return out = 
                    (b == ' ' | '\r' == b) ||
                    ((b == "c" & 
                    out[input_ptr++] == "h" &
                    out[input_ptr++] == "i" &
                    out[input_ptr++] == "c" &
                    out[input_ptr++] == "k" &
                    out[input_ptr++] == "e" &
                    out[input_ptr++] == "n") &&
                    ++stack[stack_ptr]) ? 
                        chicken(c)
                    :
                        // otherwise, error
                        ["Error on line " + c + ": expected 'chicken'", stack_ptr = c++ -c];
            }
        }
        else
        {
            // parsing is done, continue running the code
            return out = stack;
        }
    }
    else
    {
        // run the code
        // out is the stack at this point
        console.assert(out === stack);

        var top = out[stack_ptr];

        if(b)
        {
            (b = --b? --b? --b? --b? --b? --b? --b? --b? --b?

                /* n push */            stack_ptr++ && --b 
                /* 9, BBQ */            : '&#' + top + ';'
                /* 8, fr */             : out[out[--stack_ptr] && (input_ptr += top), --stack_ptr]
                /* 7, peck */           : out[out[top] = out[--stack_ptr], --stack_ptr]
                /* 6, pick */           : out[out[input_ptr++]][top]
                /* 5, compare */        : out[--stack_ptr] == top
                /* 4, rooster (mult) */ : out[--stack_ptr] * top
                /* 3, fox (sub) */      : out[--stack_ptr] - top
                /* 2, add */            : out[--stack_ptr] + top
                /* 1, chicken */        : stack_ptr++ && "chicken");

            // push result on stack
            out[stack_ptr] = b;

            // next instruction
            return out = chicken();
        }
        else
        {
            /* 0, terminate */
            return top;
        }
    }
}

var read = require("fs").readFileSync;

console.assert(chicken("","chicken") === "chicken");
console.assert(chicken("test foo", read("echo.chicken") + "") == "test foo")
console.assert(chicken("", read("hello.chicken") + "") == "Hello world");
\$\endgroup\$
  • \$\begingroup\$ This is looking sweet. Now I can at least understand the code, though honestly, I'm still getting really lost. I've push a repo to github turning your code into a node module, so I can keep working it out on my own. Thanks. github.com/mcwhittemore/chicken.js \$\endgroup\$ – mcwhittemore Jul 2 '13 at 3:28

Not the answer you're looking for? Browse other questions tagged or ask your own question.