222 lines
7.7 KiB
JavaScript
222 lines
7.7 KiB
JavaScript
/*
|
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
|
* Click nbfs://nbhost/SystemFileSystem/Templates/ClientSide/javascript.js to edit this template
|
|
*/
|
|
|
|
/**
|
|
* instrucoes iniciais para criacao da maquina de estado EVM
|
|
* */
|
|
|
|
|
|
//instrucoes das operacoes a ser realizadas pelo smart contract
|
|
const STOP = "STOP",
|
|
ADD = "ADD",
|
|
PUSH = "PUSH",
|
|
SUB = "SUB",
|
|
MULT = "MULT",
|
|
DIV = "DIV",
|
|
LT = "LT",
|
|
GT = "GT",
|
|
EQ = "EQ",
|
|
AND = "AND",
|
|
OR = "OR",
|
|
JUMP = "JUMP",
|
|
JUMPI = "JUMPI",
|
|
EXECUTION_COMPLETE = "execution_complete",
|
|
EXECUTION_LIMIT = 10000;
|
|
|
|
class Interpreter {
|
|
|
|
constructor() {
|
|
this.state = {
|
|
programCounter : 0,
|
|
stack: [],
|
|
code : [],
|
|
executionCount: 0
|
|
};
|
|
}
|
|
|
|
|
|
jump() {
|
|
const destination = this.state.stack.pop();
|
|
if(destination < 0 || destination > this.state.code.length) {
|
|
throw new Error(`invalid destination: ${destination}`);
|
|
}
|
|
this.state.programCounter = destination;
|
|
this.state.programCounter--;
|
|
}
|
|
|
|
runCode(code) {
|
|
var a = 0,
|
|
b = 0,
|
|
c = 0,
|
|
value = 0,
|
|
opcode = null;
|
|
this.state.code = code;
|
|
|
|
console.log("\n\ndbg-iniciando runCode();");
|
|
console.log("dbg-param-code=>" + code);
|
|
console.log("dbg-param-length=>" + this.state.code.length);
|
|
|
|
while(this.state.programCounter < this.state.code.length) {
|
|
this.state.executionCount++;
|
|
if(this.state.executionCount > EXECUTION_LIMIT) {
|
|
throw new Error(`check for an infinite loop; Execution limit of ${EXECUTION_LIMIT}`);
|
|
}
|
|
const opcode = this.state.code[this.state.programCounter];
|
|
console.log("dbg-while");
|
|
console.log("dbg-programcounter=>"+this.state.programCounter);
|
|
console.log("dbg-opcode=>"+opcode);
|
|
|
|
try {
|
|
switch (opcode) {
|
|
|
|
case PUSH:
|
|
console.log("dbg-case-push");
|
|
this.state.programCounter++;
|
|
if(this.state.programCounter === this.state.code.length) {
|
|
throw new Error("the push instruction canneot be least");
|
|
}
|
|
console.log("dbg-programcounter");
|
|
value = this.state.code[this.state.programCounter];
|
|
console.log("dbg-value=>"+value);
|
|
this.state.stack.push(value);
|
|
break;
|
|
|
|
case ADD:
|
|
case SUB:
|
|
case MULT:
|
|
case DIV:
|
|
case LT:
|
|
case GT:
|
|
case EQ:
|
|
case AND:
|
|
case OR:
|
|
console.log("dbg-case-multicase");
|
|
console.log("dbg-case-name=>" + opcode);
|
|
a = this.state.stack.pop();
|
|
b = this.state.stack.pop();
|
|
|
|
console.log("dbg-value-a=>" + a);
|
|
console.log("dbg-value-b=>" + b);
|
|
console.log("dbg-value-c=>" + c);
|
|
|
|
if(opcode === ADD) {
|
|
c = (a + b);
|
|
console.log("dbg-if-soma=>" + c);
|
|
};
|
|
|
|
if(opcode === SUB) {
|
|
c = (a - b);
|
|
console.log("dbg-if-subt5racao=>" + c);
|
|
};
|
|
|
|
if(opcode === MULT){
|
|
c = (a * b);
|
|
console.log("dbg-if-multiplicacao=>" + c);
|
|
};
|
|
|
|
if(opcode === DIV) {
|
|
c = (a / b);
|
|
console.log("dbg-if-divisao=>" + c);
|
|
};
|
|
|
|
if(opcode === LT) {
|
|
c = ((a < b) ? (1) : (0));
|
|
console.log("dbg-if-LT=>" + c);
|
|
};
|
|
|
|
if(opcode === GT) {
|
|
c = ((a > b) ? (1) : (0));
|
|
console.log("dbg-if-GT=>" + c);
|
|
};
|
|
|
|
if(opcode === EQ) {
|
|
c = ((a === b) ? (1) : (0));
|
|
console.log("dbg-if-EQ=>" + c);
|
|
};
|
|
|
|
if(opcode === AND) {
|
|
c = (a && b);
|
|
console.log("dbg-if-divisao=>" + c);
|
|
};
|
|
|
|
if(opcode === OR) {
|
|
c = (a || b);
|
|
console.log("dbg-if-divisao=>" + c);
|
|
};
|
|
|
|
this.state.stack.push(c);
|
|
break;
|
|
|
|
case JUMP:
|
|
this.jump();
|
|
break;
|
|
|
|
case JUMPI:
|
|
const condition = this.state.stack.pop();
|
|
if(condition) {
|
|
this.jump();
|
|
}
|
|
break;
|
|
|
|
case STOP:
|
|
console.log("dbg-case-stop");
|
|
throw new Error(EXECUTION_COMPLETE);
|
|
|
|
default:
|
|
console.log("dbg-case-default");
|
|
break;
|
|
}
|
|
|
|
} catch (error) {
|
|
if(error.message === EXECUTION_COMPLETE) {
|
|
return {
|
|
result: this.state.stack[this.state.stack.length-1]
|
|
}
|
|
}
|
|
console.log("dbg-catch-msg" + this.state.stack[this.state.stack.length - 1]);
|
|
console.log("dbg-catch-err" + error);
|
|
throw error;
|
|
// return this.state.stack[this.state.stack.length - 1];
|
|
}
|
|
|
|
this.state.programCounter++;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
console.log("resultado da soma", new Interpreter().runCode([PUSH, 10,PUSH, 5, ADD, STOP]));
|
|
console.log("resultado da SUBTRACAO", new Interpreter().runCode([PUSH, 1, PUSH, 5, SUB, STOP]));
|
|
console.log("resultado da DIVISAO", new Interpreter().runCode([PUSH, 2, PUSH, 3, DIV, STOP]));
|
|
console.log("resultado da MULTIPLICACAO", new Interpreter().runCode([PUSH, 2, PUSH, 3, MULT, STOP]));
|
|
console.log("resultado da LT", new Interpreter().runCode([PUSH, 2, PUSH, 3, LT, STOP]));
|
|
console.log("resultado da GT", new Interpreter().runCode([PUSH, 2, PUSH, 3, GT, STOP]));
|
|
console.log("resultado da EQ", new Interpreter().runCode([PUSH, 2, PUSH, 3, EQ, STOP]));
|
|
console.log("resultado da AND", new Interpreter().runCode([PUSH, 1, PUSH, 0, AND, STOP]));
|
|
console.log("resultado da OR", new Interpreter().runCode([PUSH, 1, PUSH, 0, OR, STOP]));
|
|
console.log("resultado da JUMP", new Interpreter().runCode([PUSH, 6,JUMP, PUSH, 0, "Jump successful", STOP]));
|
|
console.log("resultado da JUMPI", new Interpreter().runCode([PUSH, 8,PUSH, 1, JUMPI, PUSH, 0, "JumpI successful", STOP]));
|
|
|
|
try {
|
|
new Interpreter().runCode([PUSH, 99, JUMP, PUSH, 0, JUMP, PUSH, "jump sucessful", STOP]);
|
|
} catch(error) {
|
|
console.log("invalid destination error =>", error.message);
|
|
}
|
|
|
|
try {
|
|
new Interpreter().runCode([PUSH, 0, PUSH]);
|
|
} catch (error) {
|
|
console.log("expected invalid push error:", error.message);
|
|
}
|
|
|
|
|
|
try {
|
|
new Interpreter().runCode([PUSH, 0, JUMP, STOP]);
|
|
} catch (error) {
|
|
console.log("expected invalid execution error:", error.message);
|
|
}
|
|
|
|
|
|
|