Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class Interpreter {
- constructor(code) {
- console.log(code);
- console.log();
- [this.code, this.label] = this.search_labels( this.strip_comments(code) );
- this.ast = this.to_ast(this.code);
- //console.log(this.code);
- //console.log(this.label);
- console.log(this.ast[3].args);
- this.reg = {};
- this._cmp = false;
- this.trace = [];
- this.i_ptr = 0;
- this.output = [];
- }
- strip_comments(code) {
- return code.split('\n').map( (str) =>
- str.replace(/;.*/, '').replace(/\s+/g, ' ').replace(/\s+$/, '')
- ).filter(_=>_);
- }
- search_labels(code) {
- const labels = {};
- for(let i = 0; i < code.length; i++) {
- if(code[i].substr(-1) === ':') {
- const label = code[i].substr(0, code[i].length-1);
- const _code = [];
- while(code[++i].trim() !== 'ret' && code[i].substr(-1) !== ':')
- _code.push(code[i].trim());
- if(code[i].trim() === 'ret')
- _code.push('ret');
- else
- i--;
- labels[label] = this.to_ast(_code);
- }
- }
- return [
- code.filter( (str) => str[0] !== ' ' && str.substr(-1) !== ':' ),
- labels
- ];
- }
- split_op(str) {
- const parts = str.split(' ');
- //console.log('SPLIT_OP', str, '-', str.split(' ')[0])
- return [parts[0], parts.slice(1).join(' ').split(',')];
- }
- val_to_ast(op, val) {
- const is_num = Number.isInteger(parseInt(val));
- const type = /call|jmp|jne|je|jge|jg|jle|jl/.test(op)
- ? 'label'
- : is_num
- ? 'num'
- : val[0] === "'"
- ? 'str'
- : 'reg';
- return {
- type : type,
- val : is_num ? parseInt(val) : type === 'str' ? val.replace(/.(.+)./, '$1') : val
- };
- }
- to_ast(code) {
- return code.map(this.split_op).reduce((ast, [op, args]) => ast.concat({
- op : op,
- args : args.map( (arg) => this.val_to_ast(op, arg.trim()) )
- }), []);
- }
- get_val(arg) { return arg.type === 'reg' ? this.reg[arg.val] : arg.val; }
- mov(op) { this.reg[op.args[0].val] = this.get_val(op.args[1]); }
- inc(op) { this.reg[op.args[0].val]++; }
- dec(op) { this.reg[op.args[0].val]--; }
- add(op) { this.reg[op.args[0].val] += this.get_val(op.args[1]); }
- sub(op) { this.reg[op.args[0].val] -= this.get_val(op.args[1]); }
- mul(op) { this.reg[op.args[0].val] *= this.get_val(op.args[1]); }
- div(op) { this.reg[op.args[0].val] = parseInt( this.reg[op.args[0].val] / this.get_val(op.args[1]) ); }
- cmp(op) {
- const [a, b] = [this.get_val(op.args[0]), this.get_val(op.args[1])];
- this._cmp = a < b ? -1 : a === b ? 0 : 1;
- }
- jmp(op) {
- console.log();
- console.log('JMP', op.args[0].val);
- this.i_ptr = -1;
- this.ast = this.label[op.args[0].val];
- }
- jne(op) { if(this._cmp !== 0) this.jmp(op); }
- je(op) { if(this._cmp === 0) this.jmp(op); }
- jge(op) { if(this._cmp >= 0) this.jmp(op); }
- jg(op) { if(this._cmp > 0) this.jmp(op); }
- jle(op) { if(this._cmp <= 0) this.jmp(op); }
- jl(op) { if(this._cmp < 0) this.jmp(op); }
- call(op) {
- console.log();
- console.log('CALL', op.args[0].val);
- this.trace.push({
- ast : this.ast,
- i_ptr : this.i_ptr
- });
- this.ast = this.label[op.args[0].val];
- this.i_ptr = -1;
- }
- ret() {
- const trace = this.trace.pop();
- this.ast = trace.ast;
- this.i_ptr = trace.i_ptr;
- }
- msg(op) { op.args.forEach( (arg) => this.output.push( this.get_val(arg) ) ); }
- end() { this.i_ptr = Infinity; }
- run() {
- for(; this.i_ptr < this.ast.length; this.i_ptr++) {
- const op = this.ast[this.i_ptr];
- console.log(op.op);
- this[op.op](op);
- }
- return this;
- }
- }
- function assemblerInterpreter(code) {
- return new Interpreter(code).run().output.join('');
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement