refactored into ordered CodeTag and OpCode (same keys in a code)

This commit is contained in:
2025-01-03 21:04:03 +03:00
parent 0be8408a3a
commit 9c657167a8
+115 -80
View File
@@ -12,7 +12,9 @@ contract Push3Interpreter {
// ----------------------------------------------------- // -----------------------------------------------------
// 0. CONSTANTS // 0. CONSTANTS
// ----------------------------------------------------- // -----------------------------------------------------
uint8 internal constant OPCODE_BOOL_OFFSET = 0x6; uint8 internal constant OPCODE_INTEGER_OFFSET = 0x05;
uint8 internal constant OPCODE_BOOL_OFFSET = 0x0a;
uint8 internal constant OPCODE_LAST = OPCODE_BOOL_OFFSET + 0x10;
// ----------------------------------------------------- // -----------------------------------------------------
// 1. ENUMS // 1. ENUMS
@@ -21,18 +23,22 @@ contract Push3Interpreter {
NO_TAG, // 0 NO_TAG, // 0
INSTRUCTION, // 1 INSTRUCTION, // 1
INT_LITERAL, // 2 INT_LITERAL, // 2
SUBLIST, // 3 BOOL_LITERAL, // 3
BOOL_LITERAL // 4 SUBLIST // 4
} }
enum OpCode { enum OpCode {
NOOP, // 0 NOOP, // 0
INTEGER_PLUS, // 1 NOOP_1, // 1 - empty for INSTRUCTION
INTEGER_MINUS, // 2 NOOP_2, // 2 - empty for INT_LITERAL
INTEGER_MULT, // 3 NOOP_3, // 3 - empty for BOOL_LITERAL
INTEGER_DUP, // 4 NOOP_4, // 4 - empty for SUBLIST
INTEGER_POP, // 5 INTEGER_PLUS, // 5 - OPCODE_INTEGER_OFFSET
BOOL_DUP, // OPCODE_BOOL_OFFSET + 0 INTEGER_MINUS, // OPCODE_INTEGER_OFFSET + 1
INTEGER_MULT, // OPCODE_INTEGER_OFFSET + 2
INTEGER_DUP, // OPCODE_INTEGER_OFFSET + 3
INTEGER_POP, // OPCODE_INTEGER_OFFSET + 4
BOOL_DUP, // 10 - OPCODE_BOOL_OFFSET
BOOL_POP, // OPCODE_BOOL_OFFSET + 1 BOOL_POP, // OPCODE_BOOL_OFFSET + 1
BOOL_SWAP, // OPCODE_BOOL_OFFSET + 2 BOOL_SWAP, // OPCODE_BOOL_OFFSET + 2
BOOL_FLUSH, // OPCODE_BOOL_OFFSET + 3 BOOL_FLUSH, // OPCODE_BOOL_OFFSET + 3
@@ -175,12 +181,15 @@ contract Push3Interpreter {
// 4. SUBLIST PARSING // 4. SUBLIST PARSING
// ----------------------------------------------------- // -----------------------------------------------------
/** /**
* Token format: * Token format is combination of ordered CodeTag and OpCode:
* 0x00 => NOOP * 0x00 => NOOP/NO_TAG
* 0x01 => INTEGER_PLUS * 0x01 => INSTRUCTION => TODO: decide what to do
* 0x02 => INT_LITERAL => read next 4 bytes => int32 * 0x02 => INT_LITERAL => read next 4 bytes => int32
* 0x03 => SUBLIST => read next 2 bytes => subLen => parse that * 0x03 => BOOL_LITERAL => read next 1 byte => bool
* 0x04 => INTEGER_MINUS * 0x04 => SUBLIST => read next 2 bytes => subLen => parse that
* 0x05 => INTEGER_PLUS
* 0x06 => INTEGER_MINUS
* ... opcode list with type offsets
*/ */
function parseSublist(bytes calldata code, uint32 off, uint32 len) function parseSublist(bytes calldata code, uint32 off, uint32 len)
internal internal
@@ -206,9 +215,13 @@ contract Push3Interpreter {
count++; count++;
} }
else if (tokenType == 0x01) { else if (tokenType == 0x01) {
// INTEGER_PLUS // INSTRUCTION
temp[count] = makeInstruction(OpCode.INTEGER_PLUS); // TODO: implement what is decided
count++; // OpCode instructionOpcode = OpCode(readUint8(code,cur));
// validate instruction in range, otherwise NOOP
// temp[count] = makeInstruction(instructionOpcode);
// count++;
break; // unimplemented
} }
else if (tokenType == 0x02) { else if (tokenType == 0x02) {
// INT_LITERAL => 4 bytes // INT_LITERAL => 4 bytes
@@ -223,6 +236,17 @@ contract Push3Interpreter {
} }
} }
else if (tokenType == 0x03) { else if (tokenType == 0x03) {
// BOOL_LITERAL
if (cur + 1 <= endPos && (cur + 1) <= code.length) {
bool val = readBool(code, cur);
cur += 1;
temp[count] = makeBoolLiteral(val);
count++;
} else {
break;
}
}
else if (tokenType == 0x04) {
// SUBLIST => read 2 bytes => length // SUBLIST => read 2 bytes => length
if (cur + 2 <= endPos && (cur + 2) <= code.length) { if (cur + 2 <= endPos && (cur + 2) <= code.length) {
uint16 subLen = readUint16(code, cur); uint16 subLen = readUint16(code, cur);
@@ -240,22 +264,9 @@ contract Push3Interpreter {
break; break;
} }
} }
else if (tokenType == 0x04) { else if (tokenType <= OPCODE_LAST) {
// INTEGER_PLUS // OPCODE
temp[count] = makeInstruction(OpCode.INTEGER_MINUS); temp[count] = makeInstruction(OpCode(tokenType));
count++;
}
else if (tokenType == 0x05) {
// INTEGER_PLUS
temp[count] = makeInstruction(OpCode.INTEGER_MULT);
count++;
}
else if (tokenType == 0x06) {
temp[count] = makeInstruction(OpCode.INTEGER_DUP);
count++;
}
else if (tokenType == 0x07) {
temp[count] = makeInstruction(OpCode.INTEGER_POP);
count++; count++;
} }
else { else {
@@ -275,17 +286,19 @@ contract Push3Interpreter {
// 5. MAIN INTERPRETER // 5. MAIN INTERPRETER
// ----------------------------------------------------- // -----------------------------------------------------
function runInterpreter( function runInterpreter(
bytes calldata code, bytes calldata code, // non-empty - genetic agent (DNA)
uint256[] calldata initCodeStack, uint256[] calldata initCodeStack, // empty
uint256[] calldata initExecStack, uint256[] calldata initExecStack, // descriptors
int256[] calldata initIntStack int256[] calldata initIntStack, // 32bit word
bool[] calldata initBoolStack
) )
external external
pure pure
returns ( returns (
uint256[] memory finalCodeStack, uint256[] memory finalCodeStack,
uint256[] memory finalExecStack, uint256[] memory finalExecStack,
int256[] memory finalIntStack int256[] memory finalIntStack,
bool[] memory finalBoolStack
) )
{ {
// A) CODE STACK // A) CODE STACK
@@ -309,6 +322,13 @@ contract Push3Interpreter {
intStack[k] = initIntStack[k]; intStack[k] = initIntStack[k];
} }
// D) BOOL STACK
bool[] memory boolStack = new bool[](initBoolStack.length + 256);
uint256 boolTop = initBoolStack.length;
for (uint256 k = 0; k < initBoolStack.length; k++) {
boolStack[k] = initBoolStack[k];
}
// D) MAIN LOOP // D) MAIN LOOP
while (execTop > 0) { while (execTop > 0) {
uint256 topDesc = execStack[execTop - 1]; uint256 topDesc = execStack[execTop - 1];
@@ -321,47 +341,11 @@ contract Push3Interpreter {
if (op == OpCode.NOOP) { if (op == OpCode.NOOP) {
// do nothing // do nothing
} }
else if (op == OpCode.INTEGER_PLUS) { else if (uint8(op) <= OPCODE_INTEGER_OFFSET) {
// pop top 2 => sum (intTop, intStack) = execIntOpCode(intTop, intStack, op);
if (intTop >= 2) {
int256 a = intStack[intTop - 1];
int256 b = intStack[intTop - 2];
intTop -= 2;
intStack[intTop] = b + a;
intTop++;
}
} }
else if (op == OpCode.INTEGER_MINUS) { else if (uint8(op) <= OPCODE_BOOL_OFFSET) {
// pop top 2 => minus (boolTop, boolStack) = execBoolOpCode(boolTop, boolStack, op);
if (intTop >= 2) {
int256 a = intStack[intTop - 1];
int256 b = intStack[intTop - 2];
intTop -= 2;
intStack[intTop] = b - a;
intTop++;
}
}
else if (op == OpCode.INTEGER_MULT) {
// pop top 2 => minus
if (intTop >= 2) {
int256 a = intStack[intTop - 1];
int256 b = intStack[intTop - 2];
intTop -= 2;
intStack[intTop] = b * a;
intTop++;
}
}
else if (op == OpCode.INTEGER_DUP) {
if (intTop >= 1) {
int256 a = intStack[intTop - 1];
intStack[intTop] = a;
intTop++;
}
}
else if (op == OpCode.INTEGER_POP) {
if (intTop >= 1) {
intTop -= 1;
}
} }
} }
else if (tag == CodeTag.INT_LITERAL) { else if (tag == CodeTag.INT_LITERAL) {
@@ -369,6 +353,11 @@ contract Push3Interpreter {
intStack[intTop] = int256(val); intStack[intTop] = int256(val);
intTop++; intTop++;
} }
else if (tag == CodeTag.BOOL_LITERAL) {
bool val = extractBool(topDesc);
boolStack[boolTop] = val;
boolTop++;
}
else if (tag == CodeTag.SUBLIST) { else if (tag == CodeTag.SUBLIST) {
// parse sublist => push in reverse // parse sublist => push in reverse
uint32 off = getOffset(topDesc); uint32 off = getOffset(topDesc);
@@ -376,8 +365,8 @@ contract Push3Interpreter {
if (off + len <= code.length) { if (off + len <= code.length) {
uint256[] memory parsed = parseSublist(code, off, len); uint256[] memory parsed = parseSublist(code, off, len);
for (uint256 p = 0; p < parsed.length; p++) { for (uint256 p = 0; p < parsed.length; p++) { // index 0 1 2
execStack[execTop] = parsed[parsed.length - 1 - p]; execStack[execTop] = parsed[parsed.length - 1 - p]; // [0x01, 0x20, 0x0a]
execTop++; execTop++;
} }
} }
@@ -403,4 +392,50 @@ contract Push3Interpreter {
finalIntStack[i] = intStack[i]; finalIntStack[i] = intStack[i];
} }
} }
function execIntOpCode(uint256 intTop, int256[] memory intStack, OpCode op) internal returns (uint256, int256[] memory) {
if (op == OpCode.INTEGER_PLUS) {
// pop top 2 => sum
if (intTop >= 2) {
int256 a = intStack[intTop - 1];
int256 b = intStack[intTop - 2];
intTop -= 2;
intStack[intTop] = b + a;
intTop++;
}
}
else if (op == OpCode.INTEGER_MINUS) {
// pop top 2 => minus
if (intTop >= 2) {
int256 a = intStack[intTop - 1];
int256 b = intStack[intTop - 2];
intTop -= 2;
intStack[intTop] = b - a;
intTop++;
}
}
else if (op == OpCode.INTEGER_MULT) {
// pop top 2 => minus
if (intTop >= 2) {
int256 a = intStack[intTop - 1];
int256 b = intStack[intTop - 2];
intTop -= 2;
intStack[intTop] = b * a;
intTop++;
}
}
else if (op == OpCode.INTEGER_DUP) {
if (intTop >= 1) {
int256 a = intStack[intTop - 1];
intStack[intTop] = a;
intTop++;
}
}
else if (op == OpCode.INTEGER_POP) {
if (intTop >= 1) {
intTop -= 1;
}
}
return (intTop, intStack);
}
} }