DotJS 2012 - why 'eval' makes JS the best language in the world

Why 'eval' makes JS the best language in the world

(for writing ZX Spectrum emulators)

Matt Westcott - @gasmanic

DotJS, 30 November 2012

JSSpeccy

jsspeccy.zxdemo.org

Main loop

  while(true) {
    instruction = memory[pos];
    do_something(instruction);
    pos++;
  }

Main loop

  while(true) {
    instruction = memory[pos];
    do_something(instruction);
    pos++;
  }


  switch (instruction) {
    case 0x00:
              NOP        
    case 0x01:
          LD BC,nnnn     
    case 0x02:
           LD (BC),A     
    case 0x03:
            INC BC       
    ...
  }

ADD A,B

var addtemp = A + B;
var lookup = ((A & 0x88) >> 3) | ((B & 0x88) >> 2) | ((addtemp & 0x88) >> 1);
A = addtemp;
F = (addtemp & 0x100 ? 0x80 : 0) | flagTable1[lookup & 0x07] | flagTable2[A];

ADD A,C

var addtemp = A + C;
var lookup = ((A & 0x88) >> 3) | ((C & 0x88) >> 2) | ((addtemp & 0x88) >> 1);
A = addtemp;
F = (addtemp & 0x100 ? 0x80 : 0) | flagTable1[lookup & 0x07] | flagTable2[A];

ADD A,(HL)

var val = memory[HL];
var addtemp = A + val;
var lookup = ((A & 0x88) >> 3) | ((val & 0x88) >> 2) | ((addtemp & 0x88) >> 1);
A = addtemp;
F = (addtemp & 0x100 ? 0x80 : 0) | flagTable1[lookup & 0x07] | flagTable2[A];

ADD A,B

var addtemp = A + B;
var lookup = ((A & 0x88) >> 3) | ((B & 0x88) >> 2) | ((addtemp & 0x88) >> 1);
A = addtemp;
F = (addtemp & 0x100 ? 0x80 : 0) | flagTable1[lookup & 0x07] | flagTable2[A];

ADD A,C

var addtemp = A + C;
var lookup = ((A & 0x88) >> 3) | ((C & 0x88) >> 2) | ((addtemp & 0x88) >> 1);
A = addtemp;
F = (addtemp & 0x100 ? 0x80 : 0) | flagTable1[lookup & 0x07] | flagTable2[A];

ADD A,(HL)

var val = memory[HL];
var addtemp = A + val;
var lookup = ((A & 0x88) >> 3) | ((val & 0x88) >> 2) | ((addtemp & 0x88) >> 1);
A = addtemp;
F = (addtemp & 0x100 ? 0x80 : 0) | flagTable1[lookup & 0x07] | flagTable2[A];

We have computers to do this sort of job.

ENIAC

 

B → 

C → 

(HL) → 

template_ADD_A(x)

 

→ "ADD A,B"

→ "ADD A,C"

→ "ADD A,(HL)"

"
  window.mainLoop = function() {
    while(true) {
      instruction = memory[pos];
      switch (instruction) {"
 + "
        case 0x00:
                  NOP        "
 + "
        case 0x01:
              LD BC,nnnn     "
 + "
        case 0x02:
               LD (BC),A     "
 + "
        case 0x03:
                INC BC       "
        ...
 + "
      }
    }
  }"

eval("
    window.mainLoop = function() {
      while(true) {
        instruction = memory[pos];
        switch (instruction) {"
   + "
          case 0x00:
                    NOP        "
   + "
          case 0x01:
                LD BC,nnnn     "
   + "
          case 0x02:
                 LD (BC),A     "
   + "
          case 0x03:
                  INC BC       "
          ...
   + "
        }
      }
    }");

    window.mainLoop = function() {
      while(true) {
        instruction = memory[pos];
        switch (instruction) {
          case 0x00:
                    NOP        
          case 0x01:
                LD BC,nnnn     
          case 0x02:
                 LD (BC),A     
          case 0x03:
                  INC BC       
          ...
        }
      }
    }

CoffeeScript

F T W

Spectrum code:

0000: LD BC,1234
0003: INC B
0004: LD (BC),A
0005: RLCA
0006: INC BC
0007: LD (BC),A
0008: LD BC,5678

JS program flow:

  while(true) {
    instruction = memory[pos];
    switch (instruction) {
      case 0x00:
                NOP        
      case 0x01:
            LD BC,nnnn     
      case 0x02:
             LD (BC),A     
      case 0x03:
              INC BC       
      case 0x04:
               INC B       
      case 0x05:
               DEC B       
      case 0x06:
              LD B,nn      
      case 0x07:
               RLCA        
      ...
    }
  }

Spectrum code:

0000: LD BC,1234
0003: INC B
0004: LD (BC),A
0005: RLCA
0006: INC BC
0007: LD (BC),A
0008: LD BC,5678

JS program flow:

  while(true) {
    instruction = memory[pos];
    switch (instruction) {
      case 0x00:
                NOP        
      case 0x01:
            LD BC,nnnn     
      case 0x02:
             LD (BC),A     
      case 0x03:
              INC BC       
      case 0x04:
               INC B       
      case 0x05:
               DEC B       
      case 0x06:
              LD B,nn      
      case 0x07:
               RLCA        
      ...
    }
  }

Spectrum code:

0000: LD BC,1234
0003: INC B
0004: LD (BC),A
0005: RLCA
0006: INC BC
0007: LD (BC),A
0008: LD BC,5678

JS program flow:

  while(true) {
    instruction = memory[pos];
    switch (instruction) {
      case 0x00:
                NOP        
      case 0x01:
            LD BC,nnnn     
      case 0x02:
             LD (BC),A     
      case 0x03:
              INC BC       
      case 0x04:
               INC B       
      case 0x05:
               DEC B       
      case 0x06:
              LD B,nn      
      case 0x07:
               RLCA        
      ...
    }
  }

Spectrum code:

0000: LD BC,1234
0003: INC B
0004: LD (BC),A
0005: RLCA
0006: INC BC
0007: LD (BC),A
0008: LD BC,5678

JS program flow:

  while(true) {
    instruction = memory[pos];
    switch (instruction) {
      case 0x00:
                NOP        
      case 0x01:
            LD BC,nnnn     
      case 0x02:
             LD (BC),A     
      case 0x03:
              INC BC       
      case 0x04:
               INC B       
      case 0x05:
               DEC B       
      case 0x06:
              LD B,nn      
      case 0x07:
               RLCA        
      ...
    }
  }

Spectrum code:

0000: LD BC,1234
0003: INC B
0004: LD (BC),A
0005: RLCA
0006: INC BC
0007: LD (BC),A
0008: LD BC,5678

JS program flow:

  while(true) {
    instruction = memory[pos];
    switch (instruction) {
      case 0x00:
                NOP        
      case 0x01:
            LD BC,nnnn     
      case 0x02:
             LD (BC),A     
      case 0x03:
              INC BC       
      case 0x04:
               INC B       
      case 0x05:
               DEC B       
      case 0x06:
              LD B,nn      
      case 0x07:
               RLCA        
      ...
    }
  }

Spectrum code:

0000: LD BC,1234
0003: INC B
0004: LD (BC),A
0005: RLCA
0006: INC BC
0007: LD (BC),A
0008: LD BC,5678

JS program flow:

  while(true) {
    instruction = memory[pos];
    switch (instruction) {
      case 0x00:
                NOP        
      case 0x01:
            LD BC,nnnn     
      case 0x02:
             LD (BC),A     
      case 0x03:
              INC BC       
      case 0x04:
               INC B       
      case 0x05:
               DEC B       
      case 0x06:
              LD B,nn      
      case 0x07:
               RLCA        
      ...
    }
  }

Spectrum code:

0000: LD BC,1234
0003: INC B
0004: LD (BC),A
0005: RLCA
0006: INC BC
0007: LD (BC),A
0008: LD BC,5678

JS program flow:

  while(true) {
    instruction = memory[pos];
    switch (instruction) {
      case 0x00:
                NOP        
      case 0x01:
            LD BC,nnnn     
      case 0x02:
             LD (BC),A     
      case 0x03:
              INC BC       
      case 0x04:
               INC B       
      case 0x05:
               DEC B       
      case 0x06:
              LD B,nn      
      case 0x07:
               RLCA        
      ...
    }
  }

Spectrum code:

0000: LD BC,1234
0003: INC B
0004: LD (BC),A
0005: RLCA
0006: INC BC
0007: LD (BC),A
0008: LD BC,5678

JS program flow:

  while(true) {
    instruction = memory[pos];
    switch (instruction) {
      case 0x00:
                NOP        
      case 0x01:
            LD BC,nnnn     
      case 0x02:
             LD (BC),A     
      case 0x03:
              INC BC       
      case 0x04:
               INC B       
      case 0x05:
               DEC B       
      case 0x06:
              LD B,nn      
      case 0x07:
               RLCA        
      ...
    }
  }

Spectrum code:

0000: LD BC,1234
0003: INC B
0004: LD (BC),A
0005: RLCA
0006: INC BC
0007: LD (BC),A
0008: LD BC,5678

JS program flow:

  while(true) {
    instruction = memory[pos];
    switch (instruction) {
      case 0x00:
                NOP        
      case 0x01:
            LD BC,nnnn     
      case 0x02:
             LD (BC),A     
      case 0x03:
              INC BC       
      case 0x04:
               INC B       
      case 0x05:
               DEC B       
      case 0x06:
              LD B,nn      
      case 0x07:
               RLCA        
      ...
    }
  }

Spectrum code:

0000: LD BC,1234
0003: INC B
0004: LD (BC),A
0005: RLCA
0006: INC BC
0007: LD (BC),A
0008: LD BC,5678

JS program flow:

  while(true) {
    instruction = memory[pos];
    switch (instruction) {
      case 0x00:
                NOP        
      case 0x01:
            LD BC,nnnn     
      case 0x02:
             LD (BC),A     
      case 0x03:
              INC BC       
      case 0x04:
               INC B       
      case 0x05:
               DEC B       
      case 0x06:
              LD B,nn      
      case 0x07:
               RLCA        
      ...
    }
  }
ZX Spectrum Cassette
Nintendo Entertainment System ROM cartridge

Javascript:

where all of your end users have a really good optimising compiler

A performance gotcha:

        function() {
          eval('... some code ...')
        }
      
        function() {

          (1, eval)('... some code ...')

        }
      

"indirect eval"

The word of God?

X
God.
Douglas Crockford

eval is your friend.

Thank you!

Matt Westcott - @gasmanic

http://matt.west.co.tt/


Picture credits: U. S. Army, Bill Bertram, GrahamUk, Evan-Amos, Nzeemin (via Wikipedia); Douglas Crockford.
Slide framework: robflaherty / html-slideshow