<commit_before><!doctype html>
<html><head><meta charset="utf-8" />
<title>Art Makes Programs</title>
<style></style>
</head><body>

<script>
  
  var  stack  = []                                      // parameter stack
  var rstack  = []                                      // return stack
  var memory  = [] // TODO: make this a byte array
  
  var codes   = [] // TODO: make this a byte array
  var pc      = -1                                       // program counter
  
  function run(program) {
    pc = -1
    stack  = []
    rstack = []
    codes = program
    while(step(pc++) !== false) {}
    console.log(memory, stack)
  }
  
  function step() {
    var code = codes[pc]
    if(code == null) return false
    if(dict[code])
      return dict[code]() // TODO: map from # to code, then dict
    else
      push(code)
  }
  
  function scan_to_sub(how_far) {
    // TODO: do it more if needed
    //  % 4 // NOTE: 4 is magic
    var addr = next_exit(pc)
    if(!addr) return false                              // cause 0 addr would be silly
    return addr
  }
  
  function next_exit(offset) {
    for(var i = offset+1; i < codes.length; i++)        // +1 for luck
      if(codes[i] == 'exit') // TODO: map # to code
        return i
  }
  
  function push(val) {
    stack.push( +val )
  }
  
  function pop() {
    return stack.pop()
  }
  
  function read(addr) {
    return memory[addr] | 0
  }
  
  function write(addr, val) {
    if(addr < 0) addr = 0
    if(addr >= memory.length) addr = memory.length - 1
    memory[addr] = (val | 0) % 255 // memory values are constrained
  }
  
  var dict = {}
  dict['+']    = function() {var x = pop(); push((pop() + x) | 0)}
  dict['-']    = function() {var x = pop(); push((pop() - x) | 0)}
  dict['*']    = function() {var x = pop(); push((pop() * x) | 0)}
  dict['/']    = function() {var x = pop(); push((pop() / x) | 0)}
  
  dict['>M']   = function() {var addr = pop(); var value = pop(); write(addr, value)}
  dict['M>']   = function() {var addr = pop(); push(read(addr))}
                 
  dict['abs' ] = function() {push(Math.abs(pop()))}
  dict['max' ] = function() {push(Math.max(pop(), pop()))}
  dict['min' ] = function() {push(Math.min(pop(), pop()))}
  
  dict['drop'] = function() {pop()}
  dict['pick'] = function() {var p=pop(); push(stack[stack.length-p-1])}
  dict['roll'] = function() {var p=pop(); var x=stack[stack.length-p-1]; stack.splice(stack.length-p-1, 1); push(x)}

  dict['dup'] = function() {push(stack[stack.length-1])} // TODO: remove this later

  dict['jump'] = function() {
    var index = pop()    
    var how_far = pop()
    
    var addr = scan_to_sub(how_far)
    if(!addr) return dict['exit']()                     // YOLO
    
    var triple = [pc, index, addr]
    rstack.push(triple)
    stack.push(index)
    
    pc = addr
  } 
  
  dict['exit'] = function() {
    if(!rstack.length) return false                     // stop execution
    
    var triple = rstack.pop()
    var return_addr   = triple[0]
    var current_index = triple[1]
    var self_addr     = triple[2]
      
    if(!current_index) { // THINK: -1 ?
      pc = return_addr                                  // all done!
    } else {
      current_index--
      push(current_index)
      rstack.push([return_addr, current_index, self_addr])
      pc = self_addr
    }
  }
  
  // TESTS
  
  run([1, 2, 3, 4, '+', '*', '+'])
  if(stack[0] != 15 || !stack.length) console.error('ASDF!')
  
  memory  = [50, 0, 100, 200, 0, 0, 0, 100, 50, 0, 0]
  program = [ 10, 'jump', 'exit'  // loop sub 10 times
            , 'dup', 'dup'        // copy loop index twice
            , 1, '-'              // take one less than loop index
            , 'M>', 1, 'pick'     // grab from mem, pick loop index
            , 'M>'                // grab from mem
            , '+', 2, '/'         // average neighbors
            , 'dup', 2, 'roll'    // dup value, swap positions for >M
            , '>M'                // put it back in memory at loop index
            , 1, 'roll'           // value then address
            , 1, '-', '>M'                // put it back in memory at loop index minus one
            , 'exit']             // return from sub

  run(program)
  if(JSON.stringify(memory) != '[25,50,50,101,103,7,15,31,62,25,0]') console.error('QWERTY!')
  if(JSON.stringify(stack)  != '[]') console.error('YO!')
  
</script>
</body></html><commit_msg>compile and decompile and magic offsets galore<commit_after><!doctype html>
<html><head><meta charset="utf-8" />
<title>Art Makes Programs</title>
<style></style>
</head><body>

<script>
  
  var  stack  = []                                      // parameter stack
  var rstack  = []                                      // return stack
  var memory  = [] // TODO: make this a byte array
  
  var codes   = [] // TODO: make this a byte array
  var pc      = -1                                       // program counter
  
  function run(program) {
    pc = -1
    stack  = []
    rstack = []
    codes = program
    while(step(pc++) !== false) {}
    console.log(memory, stack)
  }
  
  function step() {
    var code = codes[pc]
    if(code == null) return false
    if(dict[code])
      return dict[code]() // TODO: map from # to code, then dict
    else
      push(code)
  }
  
  function scan_to_sub(how_far) {
    // TODO: do it more if needed
    //  % 4 // NOTE: 4 is magic
    var addr = next_exit(pc)
    if(!addr) return false                              // cause 0 addr would be silly
    return addr
  }
  
  function next_exit(offset) {
    for(var i = offset+1; i < codes.length; i++)        // +1 for luck
      if(codes[i] == 'exit') // TODO: map # to code
        return i
  }
  
  function push(val) {
    stack.push( +val )
  }
  
  function pop() {
    return stack.pop()
  }
  
  function read(addr) {
    return memory[addr] | 0
  }
  
  function write(addr, val) {
    if(addr < 0) addr = 0
    if(addr >= memory.length) addr = memory.length - 1
    memory[addr] = (val | 0) % 255 // memory values are constrained
  }
  
  // DICTIONARY
  
  var dict = {}
  dict['+']    = function() {var x = pop(); push((pop() + x) | 0)}
  dict['-']    = function() {var x = pop(); push((pop() - x) | 0)}
  dict['*']    = function() {var x = pop(); push((pop() * x) | 0)}
  dict['/']    = function() {var x = pop(); push((pop() / x) | 0)}
  
  dict['>M']   = function() {var addr = pop(); var value = pop(); write(addr, value)}
  dict['M>']   = function() {var addr = pop(); push(read(addr))}
                 
  dict['abs' ] = function() {push(Math.abs(pop()))}
  dict['max' ] = function() {push(Math.max(pop(), pop()))}
  dict['min' ] = function() {push(Math.min(pop(), pop()))}
  
  dict['drop'] = function() {pop()}
  dict['pick'] = function() {var p=pop(); push(stack[stack.length-p-1])}
  dict['roll'] = function() {var p=pop(); var x=stack[stack.length-p-1]; stack.splice(stack.length-p-1, 1); push(x)}

  dict['dup'] = function() {push(stack[stack.length-1])} // TODO: remove this later

  dict['jump'] = function() {
    var index = pop()    
    var how_far = pop()
    
    var addr = scan_to_sub(how_far)
    if(!addr) return dict['exit']()                     // YOLO
    
    var triple = [pc, index, addr]
    rstack.push(triple)
    stack.push(index)
    
    pc = addr
  } 
  
  dict['exit'] = function() {
    if(!rstack.length) return false                     // stop execution
    
    var triple = rstack.pop()
    var return_addr   = triple[0]
    var current_index = triple[1]
    var self_addr     = triple[2]
      
    if(!current_index) { // THINK: -1 ?
      pc = return_addr                                  // all done!
    } else {
      current_index--
      push(current_index)
      rstack.push([return_addr, current_index, self_addr])
      pc = self_addr
    }
  }
  
  var magic_offset = 100
  var dict_keys = Object.keys(dict)
  
  function word_to_code(word) {
    var index = dict_keys.indexOf(word)
    if(index == -1) return false
    return index
  }
  
  function code_to_word(code) {
    var index = code - magic_offset
    if(index < 0 || index > dict_keys.length) return false
    return dict_keys[index]
  }
  
  function compile(program) {
    return program.map(function(word) {
      if(word == +word) return word
      var maybe_code = word_to_code(word)
      if(maybe_code === false) return 0
      return maybe_code + magic_offset
    })
  }
  
  function decompile(bytecode) {
    return bytecode.map(function(code) {
      var maybe_word = code_to_word(code)
      if(maybe_word === false) return code
      return maybe_word
    })
  }
  
  
  // TESTS
  
  run([1, 2, 3, 4, '+', '*', '+'])
  if(stack[0] != 15 || !stack.length) console.error('ASDF!')
  
  memory  = [50, 0, 100, 200, 0, 0, 0, 100, 50, 0, 0]
  program = [ 10, 'jump', 'exit'  // loop sub 10 times
            , 'dup', 'dup'        // copy loop index twice
            , 1, '-'              // take one less than loop index
            , 'M>', 1, 'pick'     // grab from mem, pick loop index
            , 'M>'                // grab from mem
            , '+', 2, '/'         // average neighbors
            , 'dup', 2, 'roll'    // dup value, swap positions for >M
            , '>M'                // put it back in memory at loop index
            , 1, 'roll'           // value then address
            , 1, '-', '>M'                // put it back in memory at loop index minus one
            , 'exit']             // return from sub

  run(program)
  if(JSON.stringify(memory) != '[25,50,50,101,103,7,15,31,62,25,0]') console.error('QWERTY!')
  if(JSON.stringify(stack)  != '[]') console.error('YO!')
  
  if(JSON.stringify(decompile(compile(program))) != '[10,"jump","exit","dup","dup",1,"-","M>",1,"pick","M>","+",2,"/","dup",2,"roll",">M",1,"roll",1,"-",">M","exit"]') console.error('OOPS!')
  
</script>
</body></html>
{'fraction_non_alphanumeric': 0.17250101173613921, 'fraction_numerical': 0.019020639417239985, 'mean_word_length': 1.928021327014218, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 52, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '281858', 'n_tokens_mistral': 3462, 'n_tokens_neox': 3286, 'n_words': 869}