PROTOCOL FOR ESOTERIC MINIMALISM AND AVOIDANCE OF THE TURING TARPIT (PEMATT) PROTOTYPE DRAFT-III CONTENTS: *BASIC STRUCTURE *INSTRUCTIONS *PREPROCESSOR *GARBAGE COLLECTION BASIC STRUCTURE: The system consists of a stack, which shall be used for storing data. The data, on the other hand, can be of five types: * Integer-type * Integers can be of fixed length as well: *i8, i16, i32, i64, i - Signed 8/16/32/64/independent bit numbers *u8, u16, u32, u64, u - Unsigned 8/16/32/64/independent bit numbers. * Floating Point-type (Double precision) * ASCII String-type * Code-type * Array-type (1-indexed, for *now*) The code shall have the ability through various instructions to act on these values, and also to act on the stack. There shall be no registers in the esoteric CPU, with the exception of the instruction pointer, and the stack pointer. The CPU instructions shall be only of one-byte length and in ASCII only. There must be strict type checking, implemented within the CPU. All type errors must be handled like exceptions. (which shall be discussed later) INSTRUCTIONS: CHARACTER (ASCII) DESCRIPTION ------------------------------------------------------------------- > Increase top stack pointer by 1 ------------------------------------------------------------------- < Decrease top of stack pointer by 1 ------------------------------------------------------------------ ~ Toggle INSERT/OVERWRITE modes. Under INSERT mode, if the stack pointer does not point to the *actual* top of stack, and an item is pushed, the interpreter is expected to "insert" the newer item between the stack pointer, and the item after it. Under OVERWRITE mode, the item right after the top of stack is replaced with the new pushed item. The mode on initialisation is guaranteed to be INSERT. The stack pointer is incremented in both modes on push. During a pop operation in INSERT mode, the item from the stack will be purged, and the items below it will be shifted up one (or the number of items popped), and the stack pointer will be decremented. On the other hand, during OVERWRITE mode, the stack pointer will only be decremented, the items will not be removed. (This applies to all instructions which do pop operations as well.) ------------------------------------------------------------------ (...) Push string, float, integer or code to stack and increment the stack pointer. enclosed in '()'. Integers must be prefixed with i/u/i8/i16/i32/i64/u8/u16/u32/u64, e.g.: (i:247) to push the integer 247. They can also be prefixed with 'x' or 'b' to indicate hexadecimal or binary. e.g: (u16:xEFF) or (u8:b1110111). You can also push the address of labels, simply by using the 'l' prefix e.g: (l:"mylabel"). Strings must be prefixed with 's' and enclosed in '"'. e.g: (s:"Hello, World!"), to push the string "Hello, World!". Floats must be prefixed with 'f', the non-whole part is to be separated from the whole by a '.'. All floats MUST use the decimal system. e.g: (f:23.7) The 'Code' type contains code, which can be called through various instructions explained later on, they must be prefixed with 'c' and be enclosed within '"', e.g: (c:"<<(i247)") An array can be pushed by enclosing it within brackets, e.g: ([1,2,3]) or ([[]]) (jagged empty array) ------------------------------------------------------------------ + Add/Concatenate items. Depending upon type, do an add or concatenate, and pop both the items, pushing the result. Let a be the item right on stack pointer, and b be the item right on stack pointer - 1. *If both a and b are integers, then push: b+a *If both a and b are floats, then push: b+a *If a is an integer and b is a float, then convert a to float, and push b+a *If a is a float and b is an integer, round of a to an integer, and push b+a *If both a and b are strings or code, concatenate a and b, and push result. *If a is a string, and b is a integer, attempt to convert a to integer, and push b+a. If there is an error in conversion, cause an exception. *If a is an integer or float and b is a string, convert a to string, and concatenate a and b, pushing the result *If a and b are arrays of the same type, pop a and b, concatenate a into b, and push result else error out. *If 'a' is a non-array object of type b[n] (b is an array), pop a and b, then append a into b, and push b. Error out on all other circumstances. *If a is code and b is an integer or float, error out. *If b is code, and a is an integer or float, error out. *Note that the type of b (what type of integer/float it is), determines the type of the result pushed after an arithmetic operation. If there is an overflow, it would wrap back. This applies to everything and every operation not just the add operator (+). ------------------------------------------------------------------ - Subtract/Remove items. Depending upon type, do a subtract or removal operation, and pop both items, pushing result. Let a be the item right on stack pointer, and b be the item right on stack pointer - 1. *If both a and b are integers, then push: b-a *If both a and b are floats, then push: b-a *If a is an integer and b is a float, then convert a to float, and push b-a *If a is a float and b is an integer, round off a to an integer, and push b-a *If both a and b are strings or code, remove all instance of 'a' from 'b' and push the result. *If a is a string, and b is a integer, attempt to convert a to integer, and push b-a. If there is an error in conversion, cause an exception. *If a is an integer or float and b is a string, convert a to string, and remove all instance of a from b, pushing the result *If a is an array and b is an array of the same type, pop a and b, and remove all instances of items in a, from b, and push b. *If a is a non-array object of type b[n] (b is an array), pop a and b, and append a to b, and push b. Error out on all other circumstances. *If a is code and b is an integer or float, error out. *If b is code, and a is an integer or float, error out. ------------------------------------------------------------------ * Multiply operation. Let a be the item right on stack pointer, and b be the item right on stack pointer - 1. *If both a and b are integers, then push: b*a *If both a and b are floats, then push: b*a *If a is an array of type integer/float and b is an array of type integer/float, pop a and b, and multiply each instance of a with it's corresponding index of b, pushing the result. e.g: ([1,2,3])([5,6,7])* should yield: [5, 12, 21]. If the length of a is less than b, then keep multiplying through wrapping the multipliers. e.g: [1,2,3][5,6]* should yield: [5, 12, 15]. If length of a is greater than b, then keeping wrapping multiplicands. e.g: [1,2][5,6,7,8]* should yield: [5, 12, 7, 16]. Also, if the arrays multipled are of either type (integer and float), then the type of b shall be the type of the new array created. Error out if the items are not of integer or float type. *If a is a value of type float/integer and b is an array of type float/integer, pop a and b then multiply each item in b with a, and push b. Error out on all other circumstances. *If a is an integer and b is a float, then convert a to float, and push b*a *If a is a float and b is an integer, round off a to an integer, and push b*a *Error out on all other circumstances ------------------------------------------------------------------ / Divide operation. Let a be the item right on stack pointer, and b be the item right on stack pointer - 1. *If both a and b are integers, then push: b/a *If both a and b are floats, then push: b/a *If a is an array of type integer/float and b is an array of type integer/float, pop a and b, and divide each instance of b by it's corresponding index of a, pushing the result. e.g: ([25,30,35])([5,6,7])* should yield: [5, 5, 5]. The rules of array multiplication given in the '*' section, apply here as well. *If a is a value of type float/integer and b is an array of type float/integer, pop a and b then divide each item in b by a, and push b. Error out on all other circumstances. *If a is an integer and b is a float, then convert a to float, and push b/a *If a is a float and b is an integer, round off a to an integer, and push b/a *Error out on all other circumstances ------------------------------------------------------------------ % Modulo operation. (Remainder Operation) Let a be the item right on stack pointer, and b be the item right on stack pointer - 1. *If both a and b are integers, then push: b%a *If both a and b are floats, then push: b%a *Do the same as expected in multiplication/division, except, of course, the operation done should be modulus, if a and b are both arrays, or a is a non-array object of type b[n]. Error out on all other circumstances. *If a is an integer and b is a float, then convert a to float, and push b%a *If a is a float and b is an integer, round off a to an integer, and push b%a *Error out on all other circumstances ------------------------------------------------------------------ ^ Power operation. *Let a be the item right on stack, and b be the item right on stack pointer - 1 *If a and b are both integers, push b^a, in raw integer format to stack. And pop b and a. *If a and b are both floats, push b^a, in floating point format to stack. And pop b and a. *If a is an array and b is an array, of the integer/float type, pop a and b, and replace all items in b, with b[n]^a, respectively. The rules of multiplication and division apply here as well. *If a is float, and b is an integer, convert a to integer (round off), and push b^a as integer. *If a is integer, and b is float, convert a to float, and push b^a as float. ------------------------------------------------------------------ R Right Shift operation (>>) Let a be the item right on stack pointer, and b be the item right on stack pointer - 1. *If both a and b are integers, then push: b>>a *If both a and b are floats, then push: b>>a (NOTE: FLOATS WILL BE CONVERTED TO IEEE-754 ENCODING PRIOR TO BITWISE OPERATION, AND WOULD THEN BE CONVERTED BACK TO FLOATING POINT DECIMALS AFTER THE OPERATION HAS BEEN DONE.) *Error out on all other circumstances ------------------------------------------------------------------ L Left shift operation (<<) Let a be the item right on stack pointer, and b be the item right on stack pointer - 1. *If both a and b are integers, then push: b<