Advertisement
Guest User

Untitled

a guest
Oct 19th, 2018
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. class Interpreter {
  2.   constructor(code) {
  3.     console.log(code);
  4.     console.log();
  5.  
  6.     [this.code, this.label] = this.search_labels( this.strip_comments(code) );
  7.     this.ast = this.to_ast(this.code);
  8.     //console.log(this.code);
  9.     //console.log(this.label);
  10.     console.log(this.ast[3].args);
  11.    
  12.     this.reg = {};
  13.     this._cmp = false;
  14.     this.trace = [];
  15.     this.i_ptr = 0;
  16.     this.output = [];
  17.   }
  18.  
  19.   strip_comments(code) {
  20.     return code.split('\n').map( (str) =>
  21.       str.replace(/;.*/, '').replace(/\s+/g, ' ').replace(/\s+$/, '')
  22.     ).filter(_=>_);
  23.   }
  24.  
  25.   search_labels(code) {
  26.     const labels = {};
  27.    
  28.     for(let i = 0; i < code.length; i++) {
  29.       if(code[i].substr(-1) === ':') {
  30.         const label = code[i].substr(0, code[i].length-1);
  31.         const _code  = [];
  32.        
  33.         while(code[++i].trim() !== 'ret' && code[i].substr(-1) !== ':')
  34.           _code.push(code[i].trim());
  35.        
  36.         if(code[i].trim() === 'ret')
  37.           _code.push('ret');
  38.         else
  39.           i--;
  40.        
  41.         labels[label] = this.to_ast(_code);
  42.       }
  43.     }
  44.    
  45.     return [
  46.       code.filter( (str) => str[0] !== ' ' && str.substr(-1) !== ':' ),
  47.       labels
  48.     ];
  49.   }
  50.  
  51.   split_op(str) {
  52.     const parts = str.split(' ');
  53.     //console.log('SPLIT_OP', str, '-', str.split(' ')[0])
  54.     return [parts[0], parts.slice(1).join(' ').split(',')];
  55.   }
  56.  
  57.   val_to_ast(op, val) {
  58.     const is_num = Number.isInteger(parseInt(val));
  59.     const type = /call|jmp|jne|je|jge|jg|jle|jl/.test(op)
  60.       ? 'label'
  61.       : is_num
  62.         ? 'num'
  63.         : val[0] === "'"
  64.           ? 'str'
  65.           : 'reg';
  66.    
  67.     return {
  68.       type : type,
  69.       val  : is_num ? parseInt(val) : type === 'str' ? val.replace(/.(.+)./, '$1') : val
  70.     };
  71.   }
  72.  
  73.   to_ast(code) {
  74.     return code.map(this.split_op).reduce((ast, [op, args]) => ast.concat({
  75.       op   : op,
  76.       args : args.map( (arg) => this.val_to_ast(op, arg.trim()) )
  77.     }), []);
  78.   }
  79.  
  80.   get_val(arg) { return arg.type === 'reg' ? this.reg[arg.val] : arg.val; }
  81.  
  82.   mov(op) { this.reg[op.args[0].val] = this.get_val(op.args[1]); }
  83.  
  84.   inc(op) { this.reg[op.args[0].val]++; }
  85.   dec(op) { this.reg[op.args[0].val]--; }
  86.   add(op) { this.reg[op.args[0].val] += this.get_val(op.args[1]); }
  87.   sub(op) { this.reg[op.args[0].val] -= this.get_val(op.args[1]); }
  88.   mul(op) { this.reg[op.args[0].val] *= this.get_val(op.args[1]); }
  89.   div(op) { this.reg[op.args[0].val]  = parseInt( this.reg[op.args[0].val] / this.get_val(op.args[1]) ); }
  90.  
  91.   cmp(op) {
  92.     const [a, b] = [this.get_val(op.args[0]), this.get_val(op.args[1])];
  93.     this._cmp = a < b ? -1 : a === b ? 0 : 1;
  94.   }
  95.  
  96.   jmp(op) {
  97.     console.log();
  98.     console.log('JMP', op.args[0].val);
  99.     this.i_ptr = -1;
  100.     this.ast   = this.label[op.args[0].val];
  101.   }
  102.   jne(op) { if(this._cmp !== 0) this.jmp(op); }
  103.   je(op)  { if(this._cmp === 0) this.jmp(op); }
  104.   jge(op) { if(this._cmp  >= 0) this.jmp(op); }
  105.   jg(op)  { if(this._cmp   > 0) this.jmp(op); }
  106.   jle(op) { if(this._cmp  <= 0) this.jmp(op); }
  107.   jl(op)  { if(this._cmp   < 0) this.jmp(op); }
  108.  
  109.   call(op) {
  110.     console.log();
  111.     console.log('CALL', op.args[0].val);
  112.  
  113.     this.trace.push({
  114.       ast   : this.ast,
  115.       i_ptr : this.i_ptr
  116.     });
  117.    
  118.     this.ast   = this.label[op.args[0].val];
  119.     this.i_ptr = -1;
  120.   }
  121.  
  122.   ret() {
  123.     const trace = this.trace.pop();
  124.     this.ast   = trace.ast;
  125.     this.i_ptr = trace.i_ptr;
  126.   }
  127.  
  128.   msg(op) { op.args.forEach( (arg) => this.output.push( this.get_val(arg) ) ); }
  129.  
  130.   end() { this.i_ptr = Infinity; }
  131.  
  132.   run() {
  133.     for(; this.i_ptr < this.ast.length; this.i_ptr++) {
  134.       const op = this.ast[this.i_ptr];
  135.       console.log(op.op);
  136.       this[op.op](op);
  137.     }
  138.    
  139.     return this;
  140.   }
  141. }
  142.  
  143. function assemblerInterpreter(code) {
  144.     return new Interpreter(code).run().output.join('');
  145. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement