/* * 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); }